diff --git a/.github/workflows/build-and-upload-binaries-ci.yml b/.github/workflows/build-and-upload-binaries-ci.yml index 57b897d9c2..26f3ccb588 100644 --- a/.github/workflows/build-and-upload-binaries-ci.yml +++ b/.github/workflows/build-and-upload-binaries-ci.yml @@ -83,7 +83,7 @@ jobs: run: cargo install --version 0.112.0 wasm-opt - name: Build release contracts - run: make wasm + run: make contracts-wasm - name: Prepare build output shell: bash diff --git a/.github/workflows/contracts-build.yml b/.github/workflows/contracts-build.yml index 8a0a5d4122..bc7a343cb4 100644 --- a/.github/workflows/contracts-build.yml +++ b/.github/workflows/contracts-build.yml @@ -23,7 +23,7 @@ jobs: run: cargo install --version 0.112.0 wasm-opt - name: Build release contracts - run: make wasm + run: make contracts-wasm - name: Upload Mixnet Contract Artifact uses: actions/upload-artifact@v3 diff --git a/.github/workflows/nightly_build_release.yml b/.github/workflows/nightly_build_release.yml index 6ddee762e1..7687035157 100644 --- a/.github/workflows/nightly_build_release.yml +++ b/.github/workflows/nightly_build_release.yml @@ -28,7 +28,7 @@ jobs: run: git fetch --all - name: Set output variable to latest release branch id: step2 - run: echo "latest_release=$(git branch -r | grep -E 'release/v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 1 | sed 's/ origin\///')" >> $GITHUB_OUTPUT + run: echo "latest_release=$(git branch -r | grep -E 'release/v[0-9]+\.[0-9]+\.[0-9]+-' | sort -V | tail -n 1 | sed 's/ origin\///')" >> $GITHUB_OUTPUT build: needs: [get_release,matrix_prep] strategy: diff --git a/.github/workflows/sdk-docs-typescript.yml b/.github/workflows/sdk-docs-typescript.yml index 2df60dcc0b..e6ed5161f1 100644 --- a/.github/workflows/sdk-docs-typescript.yml +++ b/.github/workflows/sdk-docs-typescript.yml @@ -4,9 +4,11 @@ on: push: paths: - "sdk/typescript/**" + - "wasm/**" pull_request: paths: - "sdk/typescript/**" + - "wasm/**" jobs: build: @@ -26,17 +28,39 @@ jobs: toolchain: stable - name: Setup yarn run: npm install -g yarn + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.20' + + - name: Build branch WASM packages + run: make sdk-wasm-build + - name: Install run: yarn + - name: Build + run: yarn docs:prod:build + - name: Deploy branch to CI www (docs) + continue-on-error: true + uses: easingthemes/ssh-deploy@main + env: + SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }} + ARGS: "-rltgoDzvO --delete" + SOURCE: "dist/ts/" + REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }} + REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }} + TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/sdk-ts-docs-${{ env.GITHUB_REF_SLUG }} + EXCLUDE: "/dist/, /node_modules/" - name: Matrix - Node Install run: npm install working-directory: .github/workflows/support-files - name: Matrix - Send Notification env: NYM_NOTIFICATION_KIND: ts-packages - NYM_PROJECT_NAME: "ts-packages" - NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}" - NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}" + NYM_PROJECT_NAME: "sdk-ts-docs" + NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}/docs/sdk/typescript" + NYM_CI_WWW_LOCATION: "sdk-ts-docs-${{ env.GITHUB_REF_SLUG }}" GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}" GIT_BRANCH: "${GITHUB_REF##*/}" IS_SUCCESS: "${{ job.status == 'success' }}" diff --git a/.github/workflows/typescript-lint.yml b/.github/workflows/typescript-lint.yml index a8318364a4..bed25154a6 100644 --- a/.github/workflows/typescript-lint.yml +++ b/.github/workflows/typescript-lint.yml @@ -25,27 +25,37 @@ jobs: runs-on: custom-runner-linux steps: - uses: actions/checkout@v2 - - name: Install rsync - run: sudo apt-get install rsync - continue-on-error: true - uses: rlespinasse/github-slug-action@v3.x + - uses: actions/setup-node@v3 with: node-version: 18 + - name: Setup yarn + run: npm install -g yarn + - name: Install Rust stable uses: actions-rs/toolchain@v1 with: toolchain: stable - name: Install wasm-pack run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - - name: Setup yarn - run: npm install -g yarn + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.20' + - name: Install run: yarn + - name: Build packages - run: yarn build + run: yarn build:ci:sdk + - name: Lint - run: yarn lint && yarn tsc + run: yarn lint + - name: Typecheck with tsc + run: yarn tsc + - name: Matrix - Node Install run: npm install working-directory: .github/workflows/support-files diff --git a/.github/workflows/wasm_client_build.yml b/.github/workflows/wasm_client_build.yml deleted file mode 100644 index e71120a346..0000000000 --- a/.github/workflows/wasm_client_build.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Wasm Client - -on: - pull_request: - paths: - - 'clients/webassembly/**' - - 'clients/client-core/**' - - 'common/**' - - 'contracts/**' - - 'gateway/gateway-requests/**' - - 'nym-api/nym-api-requests/**' - -jobs: - wasm: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - target: wasm32-unknown-unknown - override: true - components: rustfmt, clippy - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown - - - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --manifest-path clients/webassembly/Cargo.toml -- --check - - - uses: actions-rs/cargo@v1 - with: - command: clippy - args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown -- -D warnings diff --git a/.github/workflows/wasm_sdk.yml b/.github/workflows/wasm_sdk.yml new file mode 100644 index 0000000000..d3f5a2813b --- /dev/null +++ b/.github/workflows/wasm_sdk.yml @@ -0,0 +1,46 @@ +name: Wasm Client + +on: + pull_request: + paths: + - 'wasm/**' + - 'clients/client-core/**' + - 'common/**' + +jobs: + wasm: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + target: wasm32-unknown-unknown + override: true + components: rustfmt, clippy + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.20' + + + - name: Install wasm-pack + run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + + - name: Install wasm-opt + run: cargo install wasm-opt + + - name: Install wasm-bindgen-cli + run: cargo install wasm-bindgen-cli + + - name: "Build" + run: make sdk-wasm-build + + - name: "Test" + run: make sdk-wasm-test + + - name: "Lint" + run: make sdk-wasm-lint diff --git a/.gitignore b/.gitignore index 21ea8966e7..aef1cee421 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,6 @@ envs/qwerty.env .parcel-cache **/.DS_Store cpu-cycles/libcpucycles/build -foxyfox.env \ No newline at end of file +foxyfox.env + +.next \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1421d63898..4134fbebda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,22 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// ## [Unreleased] +## [v1.1.31-kitkat] (2023-09-12) + +- feat: add name to `TaskClient` ([#3844]) +- added 'open_proxy', 'enabled_statistics' and 'statistics_recipient' to NR config ([#3839]) +- MixFetch: initial prototype for insecure HTTP ([#3645]) +- MixFetch: prototype implementing TLS in WASM for HTTPS ([#3644]) +- SDK: build package for NodeJS ([#3558]) +- [Issue] There is already an open connection to this client ([#2845]) + +[#3844]: https://github.com/nymtech/nym/pull/3844 +[#3839]: https://github.com/nymtech/nym/pull/3839 +[#3645]: https://github.com/nymtech/nym/issues/3645 +[#3644]: https://github.com/nymtech/nym/issues/3644 +[#3558]: https://github.com/nymtech/nym/issues/3558 +[#2845]: https://github.com/nymtech/nym/issues/2845 + ## [v1.1.30-twix] (2023-09-05) - geo_aware_provider: fix too much filtering of gateways ([#3826]) diff --git a/Cargo.lock b/Cargo.lock index 5e8ae04207..4454ef48e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1078,6 +1078,16 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +[[package]] +name = "bytecodec" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adf4c9d0bbf32eea58d7c0f812058138ee8edaf0f2802b6d03561b504729a325" +dependencies = [ + "byteorder", + "trackable 0.2.24", +] + [[package]] name = "byteorder" version = "1.4.3" @@ -1113,6 +1123,69 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "camino" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-edit" +version = "0.11.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f769ab9e8c1652d78dd0b3ec59cdaa1e2bcb3b6b39f6681b256abcdbe101cc14" +dependencies = [ + "anyhow", + "cargo_metadata", + "clap 4.3.21", + "concolor-control", + "crates-index", + "dirs-next", + "dunce", + "env_proxy", + "git2", + "hex", + "indexmap 1.9.3", + "native-tls", + "pathdiff", + "regex", + "semver 1.0.18", + "serde", + "serde_derive", + "serde_json", + "subprocess", + "termcolor", + "toml_edit 0.16.2", + "ureq", + "url", +] + +[[package]] +name = "cargo-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.18", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cast" version = "0.3.0" @@ -1343,6 +1416,7 @@ dependencies = [ "clap_lex 0.5.0", "once_cell", "strsim", + "terminal_size", ] [[package]] @@ -1439,6 +1513,23 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "concolor-control" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7104119c2f80d887239879d0c50e033cd40eac9a3f3561e0684ba7d5d654f4da" +dependencies = [ + "atty", + "bitflags 1.3.2", + "concolor-query", +] + +[[package]] +name = "concolor-query" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad159cc964ac8f9d407cbc0aa44b02436c054b541f2b4b5f06972e1efdc54bc7" + [[package]] name = "concurrent-queue" version = "2.2.0" @@ -1498,6 +1589,16 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + [[package]] name = "const-oid" version = "0.9.5" @@ -1678,6 +1779,27 @@ dependencies = [ "libc", ] +[[package]] +name = "crates-index" +version = "0.18.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "599f67b56f40863598cb30450427049935d05de2e36c61d33c050f04d7ec8cf2" +dependencies = [ + "git2", + "hex", + "home", + "memchr", + "num_cpus", + "rayon", + "rustc-hash", + "semver 1.0.18", + "serde", + "serde_derive", + "serde_json", + "smartstring", + "toml 0.5.11", +] + [[package]] name = "crc" version = "2.1.0" @@ -2419,6 +2541,16 @@ dependencies = [ "dirs-sys 0.4.1", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + [[package]] name = "dirs-sys" version = "0.3.7" @@ -2442,6 +2574,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "displaydoc" version = "0.2.4" @@ -2477,6 +2620,12 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65d09067bfacaa79114679b279d7f5885b53295b1e2cfb4e79c8e4bd3d633169" +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + [[package]] name = "dyn-clone" version = "1.0.12" @@ -2683,6 +2832,16 @@ dependencies = [ "regex", ] +[[package]] +name = "env_proxy" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a5019be18538406a43b5419a5501461f0c8b49ea7dfda0cfc32f4e51fc44be1" +dependencies = [ + "log", + "url", +] + [[package]] name = "ephemera" version = "0.1.0" @@ -2768,7 +2927,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "explorer-api" -version = "1.1.28" +version = "1.1.29" dependencies = [ "chrono", "clap 4.3.21", @@ -2822,6 +2981,22 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "extension-storage" +version = "1.2.0-rc.2" +dependencies = [ + "bip39", + "console_error_panic_hook", + "js-sys", + "serde-wasm-bindgen", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-storage", + "wasm-utils", + "zeroize", +] + [[package]] name = "extension-traits" version = "1.0.1" @@ -3294,6 +3469,8 @@ dependencies = [ "libc", "libgit2-sys", "log", + "openssl-probe", + "openssl-sys", "url", ] @@ -3303,6 +3480,27 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "gloo-net" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a66b4e3c7d9ed8d315fd6b97c8b1f74a7c6ecbbc2320e65ae7ed38b7068cc620" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "http", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "gloo-timers" version = "0.2.6" @@ -3315,6 +3513,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gloo-utils" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "group" version = "0.10.0" @@ -3531,6 +3742,9 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] [[package]] name = "hex-literal" @@ -3594,6 +3808,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "hostname" version = "0.3.1" @@ -3633,6 +3856,16 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +[[package]] +name = "httpcodec" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f49d64351430cabd543943b79d48aaf0bc95a41d9ccf5b8774c2cfd23422775" +dependencies = [ + "bytecodec", + "trackable 0.2.24", +] + [[package]] name = "httpdate" version = "1.0.3" @@ -4111,9 +4344,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -4170,6 +4403,15 @@ dependencies = [ "libc", ] +[[package]] +name = "kstring" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747" +dependencies = [ + "static_assertions", +] + [[package]] name = "language-tags" version = "0.3.2" @@ -4250,7 +4492,9 @@ checksum = "51e5ea06c26926f1002dd553fded6cfcdc9784c1f60feeb58368b4d9b07b6dba" dependencies = [ "cc", "libc", + "libssh2-sys", "libz-sys", + "openssl-sys", "pkg-config", ] @@ -5041,6 +5285,20 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libssh2-sys" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b094a36eb4b8b8c8a7b4b8ae43b2944502be3e59cd87687595cf6b0a71b3f4ca" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + [[package]] name = "libz-sys" version = "1.1.12" @@ -5300,6 +5558,29 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mix-fetch-wasm" +version = "1.2.0-rc.2" +dependencies = [ + "futures", + "js-sys", + "nym-ordered-buffer", + "nym-service-providers-common", + "nym-socks5-requests", + "rand 0.7.3", + "reqwest", + "serde", + "serde-wasm-bindgen", + "thiserror", + "tokio", + "tsify", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-client-core", + "wasm-utils", +] + [[package]] name = "multer" version = "2.1.0" @@ -5547,6 +5828,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + [[package]] name = "notify" version = "5.2.0" @@ -5638,7 +5928,7 @@ dependencies = [ [[package]] name = "nym-api" -version = "1.1.29" +version = "1.1.30" dependencies = [ "actix-web", "anyhow", @@ -5785,7 +6075,7 @@ dependencies = [ [[package]] name = "nym-cli" -version = "1.1.28" +version = "1.1.29" dependencies = [ "anyhow", "base64 0.13.1", @@ -5858,7 +6148,7 @@ dependencies = [ [[package]] name = "nym-client" -version = "1.1.28" +version = "1.1.29" dependencies = [ "clap 4.3.21", "dirs 4.0.0", @@ -5941,6 +6231,28 @@ dependencies = [ "zeroize", ] +[[package]] +name = "nym-client-wasm" +version = "1.2.0-rc.2" +dependencies = [ + "anyhow", + "futures", + "js-sys", + "nym-node-tester-utils", + "nym-node-tester-wasm", + "rand 0.7.3", + "serde", + "serde-wasm-bindgen", + "serde_json", + "thiserror", + "tsify", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test", + "wasm-client-core", + "wasm-utils", +] + [[package]] name = "nym-client-websocket-requests" version = "0.1.0" @@ -6166,7 +6478,7 @@ dependencies = [ [[package]] name = "nym-gateway" -version = "1.1.28" +version = "1.1.29" dependencies = [ "anyhow", "async-trait", @@ -6220,6 +6532,7 @@ version = "0.1.0" dependencies = [ "futures", "getrandom 0.2.10", + "gloo-utils", "log", "nym-bandwidth-controller", "nym-coconut-interface", @@ -6277,6 +6590,21 @@ dependencies = [ "serde", ] +[[package]] +name = "nym-http-requests" +version = "0.1.0" +dependencies = [ + "bytecodec", + "bytes", + "http", + "httpcodec", + "nym-ordered-buffer", + "nym-service-providers-common", + "nym-socks5-requests", + "thiserror", + "url", +] + [[package]] name = "nym-inclusion-probability" version = "0.1.0" @@ -6321,7 +6649,7 @@ dependencies = [ [[package]] name = "nym-mixnode" -version = "1.1.29" +version = "1.1.30" dependencies = [ "anyhow", "bs58 0.4.0", @@ -6439,7 +6767,7 @@ dependencies = [ [[package]] name = "nym-network-requester" -version = "1.1.28" +version = "1.1.29" dependencies = [ "anyhow", "async-file-watcher", @@ -6486,7 +6814,7 @@ dependencies = [ [[package]] name = "nym-network-statistics" -version = "1.1.28" +version = "1.1.29" dependencies = [ "dirs 4.0.0", "log", @@ -6520,6 +6848,26 @@ dependencies = [ "wasm-utils", ] +[[package]] +name = "nym-node-tester-wasm" +version = "1.2.0-rc.2" +dependencies = [ + "futures", + "js-sys", + "nym-node-tester-utils", + "rand 0.7.3", + "serde", + "serde-wasm-bindgen", + "thiserror", + "tokio", + "tsify", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-client-core", + "wasm-utils", + "wasmtimer", +] + [[package]] name = "nym-nonexhaustive-delayqueue" version = "0.1.0" @@ -6587,9 +6935,13 @@ dependencies = [ "anyhow", "async-trait", "bip39", + "bytecodec", + "bytes", "dotenvy", "futures", "hex", + "http", + "httpcodec", "libp2p 0.51.0", "log", "nym-bandwidth-controller", @@ -6601,7 +6953,10 @@ dependencies = [ "nym-crypto", "nym-gateway-requests", "nym-network-defaults", + "nym-ordered-buffer", + "nym-service-providers-common", "nym-socks5-client-core", + "nym-socks5-requests", "nym-sphinx", "nym-task", "nym-topology", @@ -6651,7 +7006,7 @@ dependencies = [ [[package]] name = "nym-socks5-client" -version = "1.1.28" +version = "1.1.29" dependencies = [ "clap 4.3.21", "lazy_static", @@ -6967,6 +7322,7 @@ dependencies = [ "nym-sphinx-routing", "nym-sphinx-types", "rand 0.7.3", + "semver 0.11.0", "thiserror", ] @@ -7077,6 +7433,15 @@ dependencies = [ "ts-rs", ] +[[package]] +name = "nym-wasm-sdk" +version = "1.2.0-rc.2" +dependencies = [ + "mix-fetch-wasm", + "nym-client-wasm", + "nym-node-tester-wasm", +] + [[package]] name = "object" version = "0.31.1" @@ -8831,6 +9196,18 @@ dependencies = [ "webpki 0.22.0", ] +[[package]] +name = "rustls" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.4", + "sct 0.7.0", +] + [[package]] name = "rustls-native-certs" version = "0.5.0" @@ -8852,6 +9229,26 @@ dependencies = [ "base64 0.21.2", ] +[[package]] +name = "rustls-webpki" +version = "0.100.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e98ff011474fa39949b7e5c0428f9b4937eda7da7848bbb947786b7be0b27dab" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -8954,7 +9351,7 @@ checksum = "109da1e6b197438deb6db99952990c7f959572794b80ff93707d55a232545e7c" dependencies = [ "proc-macro2", "quote", - "serde_derive_internals", + "serde_derive_internals 0.26.0", "syn 1.0.109", ] @@ -8990,6 +9387,18 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sdk-version-bump" +version = "0.1.0" +dependencies = [ + "anyhow", + "cargo-edit", + "clap 4.3.21", + "semver 1.0.18", + "serde", + "serde_json", +] + [[package]] name = "sdp" version = "0.5.3" @@ -9076,6 +9485,9 @@ name = "semver" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +dependencies = [ + "serde", +] [[package]] name = "semver-parser" @@ -9161,6 +9573,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "serde_derive_internals" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "serde_json" version = "1.0.104" @@ -9369,6 +9792,18 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +[[package]] +name = "smartstring" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" +dependencies = [ + "autocfg 1.1.0", + "serde", + "static_assertions", + "version_check", +] + [[package]] name = "snafu" version = "0.7.5" @@ -9428,6 +9863,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "socks" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" +dependencies = [ + "byteorder", + "libc", + "winapi", +] + [[package]] name = "soketto" version = "0.7.1" @@ -9698,6 +10144,16 @@ dependencies = [ "tokio-rustls 0.23.4", ] +[[package]] +name = "ssl-inject" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap 4.3.21", + "hex", + "tokio", +] + [[package]] name = "stable-pattern" version = "0.1.0" @@ -9798,6 +10254,16 @@ dependencies = [ "webrtc-util", ] +[[package]] +name = "subprocess" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2e86926081dda636c546d8c5e641661049d7562a68f5488be4a1f7f66f6086" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "substring" version = "1.4.5" @@ -10036,6 +10502,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" +dependencies = [ + "rustix 0.37.23", + "windows-sys 0.48.0", +] + [[package]] name = "textwrap" version = "0.16.0" @@ -10341,8 +10817,17 @@ checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" dependencies = [ "serde", "serde_spanned", - "toml_datetime", - "toml_edit", + "toml_datetime 0.6.3", + "toml_edit 0.19.14", +] + +[[package]] +name = "toml_datetime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" +dependencies = [ + "serde", ] [[package]] @@ -10354,6 +10839,20 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_edit" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd30deba9a1cd7153c22aecf93e86df639e7b81c622b0af8d9255e989991a7b7" +dependencies = [ + "indexmap 1.9.3", + "itertools", + "kstring", + "nom8", + "serde", + "toml_datetime 0.5.1", +] + [[package]] name = "toml_edit" version = "0.19.14" @@ -10363,7 +10862,7 @@ dependencies = [ "indexmap 2.0.0", "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.6.3", "winnow", ] @@ -10527,6 +11026,35 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "trackable" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98abb9e7300b9ac902cc04920945a874c1973e08c310627cc4458c04b70dd32" +dependencies = [ + "trackable 1.3.0", + "trackable_derive", +] + +[[package]] +name = "trackable" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15bd114abb99ef8cee977e517c8f37aee63f184f2d08e3e6ceca092373369ae" +dependencies = [ + "trackable_derive", +] + +[[package]] +name = "trackable_derive" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebeb235c5847e2f82cfe0f07eb971d1e5f6804b18dac2ae16349cc604380f82f" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "trust-dns-proto" version = "0.22.0" @@ -10617,6 +11145,32 @@ dependencies = [ "termcolor", ] +[[package]] +name = "tsify" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b26cf145f2f3b9ff84e182c448eaf05468e247f148cf3d2a7d67d78ff023a0" +dependencies = [ + "gloo-utils", + "serde", + "serde-wasm-bindgen", + "serde_json", + "tsify-macros", + "wasm-bindgen", +] + +[[package]] +name = "tsify-macros" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a94b0f0954b3e59bfc2c246b4c8574390d94a4ad4ad246aaf2fb07d7dfd3b47" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals 0.28.0", + "syn 2.0.28", +] + [[package]] name = "tungstenite" version = "0.13.0" @@ -10852,6 +11406,25 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0976c77def3f1f75c4ef892a292c31c0bbe9e3d0702c63044d7c76db298171a3" +[[package]] +name = "ureq" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9" +dependencies = [ + "base64 0.21.2", + "log", + "native-tls", + "once_cell", + "rustls 0.21.7", + "rustls-webpki 0.100.2", + "serde", + "serde_json", + "socks", + "url", + "webpki-roots 0.23.1", +] + [[package]] name = "url" version = "2.4.0" @@ -11036,9 +11609,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -11046,24 +11619,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.33" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" dependencies = [ "cfg-if", "js-sys", @@ -11073,9 +11646,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -11083,22 +11656,93 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e6e302a7ea94f83a6d09e78e7dc7d9ca7b186bc2829c24a22d0753efd680671" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "wasm-client-core" +version = "0.1.0" +dependencies = [ + "async-trait", + "console_error_panic_hook", + "js-sys", + "nym-bandwidth-controller", + "nym-client-core", + "nym-config", + "nym-credential-storage", + "nym-crypto", + "nym-gateway-client", + "nym-sphinx", + "nym-sphinx-acknowledgements", + "nym-task", + "nym-topology", + "nym-validator-client", + "rand 0.7.3", + "serde", + "serde-wasm-bindgen", + "thiserror", + "tsify", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-storage", + "wasm-utils", + "zeroize", +] + +[[package]] +name = "wasm-storage" +version = "0.1.0" +dependencies = [ + "async-trait", + "futures", + "indexed_db_futures", + "js-sys", + "nym-store-cipher", + "serde", + "serde-wasm-bindgen", + "thiserror", + "wasm-bindgen", + "wasm-utils", +] [[package]] name = "wasm-timer" @@ -11121,12 +11765,9 @@ version = "0.1.0" dependencies = [ "futures", "getrandom 0.2.10", - "indexed_db_futures", + "gloo-net", + "gloo-utils", "js-sys", - "nym-store-cipher", - "serde", - "serde-wasm-bindgen", - "thiserror", "tungstenite 0.13.0", "wasm-bindgen", "wasm-bindgen-futures", @@ -11149,9 +11790,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", @@ -11195,6 +11836,15 @@ dependencies = [ "webpki 0.22.0", ] +[[package]] +name = "webpki-roots" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" +dependencies = [ + "rustls-webpki 0.100.2", +] + [[package]] name = "webrtc" version = "0.6.0" diff --git a/Cargo.toml b/Cargo.toml index a1634e02d2..5099ec2098 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,7 @@ members = [ "common/crypto", "common/dkg", "common/execute", + "common/http-requests", "common/inclusion-probability", "common/ledger", "common/mixnode-common", @@ -73,7 +74,9 @@ members = [ "common/task", "common/topology", "common/types", - "common/wasm-utils", + "common/wasm/client-core", + "common/wasm/storage", + "common/wasm/utils", "explorer-api", "explorer-api/explorer-api-requests", "explorer-api/explorer-client", @@ -87,11 +90,18 @@ members = [ "service-providers/network-requester", "service-providers/network-statistics", "nym-api", + "nym-browser-extension/storage", "nym-api/nym-api-requests", "nym-outfox", + "tools/internal/ssl-inject", + "tools/internal/sdk-version-bump", "tools/nym-cli", "tools/nym-nr-query", - "tools/ts-rs-cli" + "tools/ts-rs-cli", + "wasm/client", + "wasm/full-nym-wasm", + "wasm/mix-fetch", + "wasm/node-tester", ] default-members = [ @@ -105,7 +115,7 @@ default-members = [ "explorer-api", ] -exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "nym-browser-extension/storage", "cpu-cycles"] +exclude = ["explorer", "contracts", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "cpu-cycles"] [workspace.package] authors = ["Nym Technologies SA"] @@ -117,7 +127,7 @@ license = "Apache-2.0" [workspace.dependencies] anyhow = "1.0.71" -async-trait = "0.1.64" +async-trait = "0.1.68" bip39 = { version = "2.0.0", features = ["zeroize"] } cfg-if = "1.0.0" cosmwasm-derive = "=1.3.0" @@ -156,4 +166,11 @@ url = "2.4" zeroize = "1.6.0" # wasm-related dependencies +gloo-utils = "0.1.7" +js-sys = "0.3.63" +serde-wasm-bindgen = "0.5.0" +tsify = "0.4.5" +wasm-bindgen = "0.2.86" +wasm-bindgen-futures = "0.4.37" wasmtimer = "0.2.0" +web-sys = "0.3.63" diff --git a/Makefile b/Makefile index 6fc92e55f8..c74994904e 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,21 @@ # Default target all: test -test: clippy-all cargo-test wasm fmt +test: clippy-all cargo-test contracts-wasm sdk-wasm-test fmt test-all: test cargo-test-expensive -no-clippy: build cargo-test wasm fmt +no-clippy: build cargo-test contracts-wasm fmt fmt-browser-extension-storage happy: fmt clippy-happy test +build: sdk-wasm-build build-browser-extension-storage + # Building release binaries is a little manual as we can't just build --release # on all workspaces. -build-release: build-release-main wasm +build-release: build-release-main contracts-wasm + +clippy: sdk-wasm-lint clippy-browser-extension-storage # Deprecated # For backwards compatibility @@ -43,6 +47,9 @@ test-$(1): test-expensive-$(1): cargo test --manifest-path $(2)/Cargo.toml --workspace -- --ignored +build-standalone-$(1): + cargo build --manifest-path $(2)/Cargo.toml $(3) + build-$(1): cargo build --manifest-path $(2)/Cargo.toml --workspace $(3) @@ -74,7 +81,7 @@ endef $(eval $(call add_cargo_workspace,main,.)) $(eval $(call add_cargo_workspace,contracts,contracts,--lib --target wasm32-unknown-unknown)) -$(eval $(call add_cargo_workspace,wasm-client,clients/webassembly,--target wasm32-unknown-unknown)) +#$(eval $(call add_cargo_workspace,wasm-client,clients/webassembly,--target wasm32-unknown-unknown)) $(eval $(call add_cargo_workspace,wallet,nym-wallet,)) $(eval $(call add_cargo_workspace,connect,nym-connect/desktop)) @@ -88,6 +95,67 @@ build-explorer-api: build-nym-cli: cargo build -p nym-cli --release +build-browser-extension-storage: + cargo build -p extension-storage --target wasm32-unknown-unknown + +fmt-browser-extension-storage: + cargo fmt -p extension-storage -- --check + +clippy-browser-extension-storage: + cargo clippy -p extension-storage --target wasm32-unknown-unknown -- -Dwarnings + +sdk-wasm: sdk-wasm-build sdk-wasm-test sdk-wasm-lint + +sdk-wasm-build: + # browser storage + $(MAKE) -C nym-browser-extension/storage wasm-pack + + # client + $(MAKE) -C wasm/client build + + # node-tester + $(MAKE) -C wasm/node-tester build + + # mix-fetch + $(MAKE) -C wasm/mix-fetch build + + # full + $(MAKE) -C wasm/full-nym-wasm build-full + +# run this from npm/yarn to ensure tools are in the path, e.g. yarn build:sdk from root of repo +sdk-typescript-build: + lerna run --scope @nymproject/sdk build --stream + lerna run --scope @nymproject/mix-fetch build --stream + lerna run --scope @nymproject/node-tester build --stream + +sdk-wasm-test: +# # client +# cargo test -p nym-client-wasm --target wasm32-unknown-unknown +# +# # node-tester +# cargo test -p nym-node-tester-wasm --target wasm32-unknown-unknown +# +# # mix-fetch +# #cargo test -p nym-wasm-sdk --target wasm32-unknown-unknown +# +# # full +# cargo test -p nym-wasm-sdk --target wasm32-unknown-unknown + + +sdk-wasm-lint: + # client + cargo clippy -p nym-client-wasm --target wasm32-unknown-unknown -- -Dwarnings + + # node-tester + cargo clippy -p nym-node-tester-wasm --target wasm32-unknown-unknown -- -Dwarnings + + # mix-fetch + $(MAKE) -C wasm/mix-fetch check-fmt + + # full + cargo clippy -p nym-wasm-sdk --target wasm32-unknown-unknown -- -Dwarnings + + # ----------------------------------------------------------------------------- # Build contracts ready for deploy # ----------------------------------------------------------------------------- @@ -98,12 +166,12 @@ MIXNET_CONTRACT=$(CONTRACTS_OUT_DIR)/mixnet_contract.wasm SERVICE_PROVIDER_DIRECTORY_CONTRACT=$(CONTRACTS_OUT_DIR)/nym_service_provider_directory.wasm NAME_SERVICE_CONTRACT=$(CONTRACTS_OUT_DIR)/nym_name_service.wasm -wasm: wasm-build wasm-opt +contracts-wasm: contracts-wasm-build contracts-wasm-opt -wasm-build: +contracts-wasm-build: RUSTFLAGS='-C link-arg=-s' cargo build --lib --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown -wasm-opt: +contracts-wasm-opt: wasm-opt --disable-sign-ext -Os $(VESTING_CONTRACT) -o $(VESTING_CONTRACT) wasm-opt --disable-sign-ext -Os $(MIXNET_CONTRACT) -o $(MIXNET_CONTRACT) wasm-opt --disable-sign-ext -Os $(SERVICE_PROVIDER_DIRECTORY_CONTRACT) -o $(SERVICE_PROVIDER_DIRECTORY_CONTRACT) @@ -117,7 +185,7 @@ contract-schema: # ----------------------------------------------------------------------------- # NOTE: this seems deprecated an not needed anymore? -mixnet-opt: wasm +mixnet-opt: contracts-wasm cd contracts/mixnet && make opt generate-typescript: diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 1143f4ad60..8b7f695260 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-client" -version = "1.1.28" +version = "1.1.29" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] description = "Implementation of the Nym Client" edition = "2021" diff --git a/clients/native/src/client/config/old_config_v1_1_20_2.rs b/clients/native/src/client/config/old_config_v1_1_20_2.rs index 6f4686b063..30969b0f12 100644 --- a/clients/native/src/client/config/old_config_v1_1_20_2.rs +++ b/clients/native/src/client/config/old_config_v1_1_20_2.rs @@ -1,8 +1,13 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::client::config::persistence::ClientPaths; -use crate::client::config::{default_config_filepath, Config, Socket, SocketType}; +use crate::{ + client::config::{ + default_config_filepath, persistence::ClientPaths, Config, Socket, SocketType, + }, + error::ClientError, +}; + use nym_bin_common::logging::LoggingSettings; use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2; use nym_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as BaseConfigV1_1_20_2; @@ -43,18 +48,18 @@ impl ConfigV1_1_20_2 { // in this upgrade, gateway endpoint configuration was moved out of the config file, // so its returned to be stored elsewhere. - pub fn upgrade(self) -> (Config, GatewayEndpointConfig) { + pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig), ClientError> { let gateway_details = self.base.client.gateway_endpoint.clone().into(); let config = Config { base: self.base.into(), socket: self.socket.into(), storage_paths: ClientPaths { - common_paths: self.storage_paths.common_paths.upgrade_default(), + common_paths: self.storage_paths.common_paths.upgrade_default()?, }, logging: self.logging, }; - (config, gateway_details) + Ok((config, gateway_details)) } } diff --git a/clients/native/src/commands/mod.rs b/clients/native/src/commands/mod.rs index 6badc58748..e1896bcfb6 100644 --- a/clients/native/src/commands/mod.rs +++ b/clients/native/src/commands/mod.rs @@ -157,7 +157,7 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result { let updated_step1: ConfigV1_1_20 = old_config.into(); let updated_step2: ConfigV1_1_20_2 = updated_step1.into(); - let (updated, gateway_config) = updated_step2.upgrade(); + let (updated, gateway_config) = updated_step2.upgrade()?; persist_gateway_details(&updated, gateway_config)?; updated.save_to_default_location()?; @@ -177,7 +177,7 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result { info!("It is going to get updated to the current specification."); let updated_step1: ConfigV1_1_20_2 = old_config.into(); - let (updated, gateway_config) = updated_step1.upgrade(); + let (updated, gateway_config) = updated_step1.upgrade()?; persist_gateway_details(&updated, gateway_config)?; updated.save_to_default_location()?; @@ -194,7 +194,7 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result { info!("It seems the client is using <= v1.1.20_2 config template."); info!("It is going to get updated to the current specification."); - let (updated, gateway_config) = old_config.upgrade(); + let (updated, gateway_config) = old_config.upgrade()?; persist_gateway_details(&updated, gateway_config)?; updated.save_to_default_location()?; diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index c13f3b8525..03b6fcf5e9 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-socks5-client" -version = "1.1.28" +version = "1.1.29" authors = ["Dave Hrycyszyn "] description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" edition = "2021" diff --git a/clients/socks5/src/commands/mod.rs b/clients/socks5/src/commands/mod.rs index d2b37b5a84..f9e876015d 100644 --- a/clients/socks5/src/commands/mod.rs +++ b/clients/socks5/src/commands/mod.rs @@ -199,7 +199,7 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result { let updated_step1: ConfigV1_1_20 = old_config.into(); let updated_step2: ConfigV1_1_20_2 = updated_step1.into(); - let (updated, gateway_config) = updated_step2.upgrade(); + let (updated, gateway_config) = updated_step2.upgrade()?; persist_gateway_details(&updated, gateway_config)?; updated.save_to_default_location()?; @@ -219,7 +219,7 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result { info!("It is going to get updated to the current specification."); let updated_step1: ConfigV1_1_20_2 = old_config.into(); - let (updated, gateway_config) = updated_step1.upgrade(); + let (updated, gateway_config) = updated_step1.upgrade()?; persist_gateway_details(&updated, gateway_config)?; updated.save_to_default_location()?; @@ -236,7 +236,7 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result { info!("It seems the client is using <= v1.1.20_2 config template."); info!("It is going to get updated to the current specification."); - let (updated, gateway_config) = old_config.upgrade(); + let (updated, gateway_config) = old_config.upgrade()?; persist_gateway_details(&updated, gateway_config)?; updated.save_to_default_location()?; diff --git a/clients/socks5/src/config/old_config_v1_1_20_2.rs b/clients/socks5/src/config/old_config_v1_1_20_2.rs index 47d6dabe3f..998bd90b32 100644 --- a/clients/socks5/src/config/old_config_v1_1_20_2.rs +++ b/clients/socks5/src/config/old_config_v1_1_20_2.rs @@ -1,17 +1,21 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::persistence::SocksClientPaths; -use crate::config::{default_config_filepath, Config}; +use crate::{ + config::{default_config_filepath, persistence::SocksClientPaths, Config}, + error::Socks5ClientError, +}; + use nym_bin_common::logging::LoggingSettings; use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2; use nym_client_core::config::GatewayEndpointConfig; use nym_config::read_config_from_toml_file; -pub use nym_socks5_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as CoreConfigV1_1_20_2; use serde::{Deserialize, Serialize}; use std::io; use std::path::Path; +pub use nym_socks5_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as CoreConfigV1_1_20_2; + #[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)] pub struct SocksClientPathsV1_1_20_2 { #[serde(flatten)] @@ -39,16 +43,16 @@ impl ConfigV1_1_20_2 { // in this upgrade, gateway endpoint configuration was moved out of the config file, // so its returned to be stored elsewhere. - pub fn upgrade(self) -> (Config, GatewayEndpointConfig) { + pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig), Socks5ClientError> { let gateway_details = self.core.base.client.gateway_endpoint.clone().into(); let config = Config { core: self.core.into(), storage_paths: SocksClientPaths { - common_paths: self.storage_paths.common_paths.upgrade_default(), + common_paths: self.storage_paths.common_paths.upgrade_default()?, }, logging: self.logging, }; - (config, gateway_details) + Ok((config, gateway_details)) } } diff --git a/clients/webassembly/.appveyor.yml b/clients/webassembly/.appveyor.yml deleted file mode 100644 index 50910bd6f3..0000000000 --- a/clients/webassembly/.appveyor.yml +++ /dev/null @@ -1,11 +0,0 @@ -install: - - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - - if not defined RUSTFLAGS rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly - - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - - rustc -V - - cargo -V - -build: false - -test_script: - - cargo test --locked diff --git a/clients/webassembly/.cargo/config.toml b/clients/webassembly/.cargo/config.toml deleted file mode 100644 index 435ed755ec..0000000000 --- a/clients/webassembly/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[build] -target = "wasm32-unknown-unknown" \ No newline at end of file diff --git a/clients/webassembly/.gitignore b/clients/webassembly/.gitignore deleted file mode 100644 index 5b7187cad5..0000000000 --- a/clients/webassembly/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -/target -**/*.rs.bk -bin/ -pkg/ -wasm-pack.log -node_modules \ No newline at end of file diff --git a/clients/webassembly/.travis.yml b/clients/webassembly/.travis.yml deleted file mode 100644 index 7a913256e8..0000000000 --- a/clients/webassembly/.travis.yml +++ /dev/null @@ -1,69 +0,0 @@ -language: rust -sudo: false - -cache: cargo - -matrix: - include: - - # Builds with wasm-pack. - - rust: beta - env: RUST_BACKTRACE=1 - addons: - firefox: latest - chrome: stable - before_script: - - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) - - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) - - cargo install-update -a - - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f - script: - - cargo generate --git . --name testing - # Having a broken Cargo.toml (in that it has curlies in fields) anywhere - # in any of our parent dirs is problematic. - - mv Cargo.toml Cargo.toml.tmpl - - cd testing - - wasm-pack build - - wasm-pack test --chrome --firefox --headless - - # Builds on nightly. - - rust: nightly - env: RUST_BACKTRACE=1 - before_script: - - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) - - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) - - cargo install-update -a - - rustup target add wasm32-unknown-unknown - script: - - cargo generate --git . --name testing - - mv Cargo.toml Cargo.toml.tmpl - - cd testing - - cargo check - - cargo check --target wasm32-unknown-unknown - - cargo check --no-default-features - - cargo check --target wasm32-unknown-unknown --no-default-features - - cargo check --no-default-features --features console_error_panic_hook - - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook - - cargo check --no-default-features --features "console_error_panic_hook wee_alloc" - - cargo check --target wasm32-unknown-unknown --no-default-features --features "console_error_panic_hook wee_alloc" - - # Builds on beta. - - rust: beta - env: RUST_BACKTRACE=1 - before_script: - - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) - - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) - - cargo install-update -a - - rustup target add wasm32-unknown-unknown - script: - - cargo generate --git . --name testing - - mv Cargo.toml Cargo.toml.tmpl - - cd testing - - cargo check - - cargo check --target wasm32-unknown-unknown - - cargo check --no-default-features - - cargo check --target wasm32-unknown-unknown --no-default-features - - cargo check --no-default-features --features console_error_panic_hook - - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook - # Note: no enabling the `wee_alloc` feature here because it requires - # nightly for now. diff --git a/clients/webassembly/Cargo.lock b/clients/webassembly/Cargo.lock deleted file mode 100644 index e39f1ef98c..0000000000 --- a/clients/webassembly/Cargo.lock +++ /dev/null @@ -1,5559 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array 0.14.7", -] - -[[package]] -name = "aes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" -dependencies = [ - "cfg-if 1.0.0", - "cipher 0.3.0", - "cpufeatures", - "ctr 0.8.0", - "opaque-debug 0.3.0", -] - -[[package]] -name = "aes" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" -dependencies = [ - "cfg-if 1.0.0", - "cipher 0.4.4", - "cpufeatures", -] - -[[package]] -name = "aes-gcm" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237" -dependencies = [ - "aead", - "aes 0.8.3", - "cipher 0.4.4", - "ctr 0.9.2", - "ghash", - "subtle 2.4.1", -] - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom 0.2.10", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" -dependencies = [ - "cfg-if 1.0.0", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8f9420f797f2d9e935edf629310eb938a0d839f984e25327f3c7eed22300c" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - -[[package]] -name = "anstream" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is-terminal", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" - -[[package]] -name = "anstyle-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "anstyle-wincon" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" -dependencies = [ - "anstyle", - "windows-sys", -] - -[[package]] -name = "anyhow" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" - -[[package]] -name = "argon2" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e554a8638bdc1e4eae9984845306cc95f8a9208ba8d49c3859fd958b46774d" -dependencies = [ - "base64ct", - "blake2 0.10.6", - "cpufeatures", - "password-hash", -] - -[[package]] -name = "arrayref" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "async-trait" -version = "0.1.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "atoi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" -dependencies = [ - "num-traits", -] - -[[package]] -name = "atoi" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" -dependencies = [ - "num-traits", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" -dependencies = [ - "addr2line", - "cc", - "cfg-if 1.0.0", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "bip32" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e141fb0f8be1c7b45887af94c88b182472b57c96b56773250ae00cd6a14a164" -dependencies = [ - "bs58 0.5.0", - "hmac 0.12.1", - "k256 0.13.1", - "once_cell", - "pbkdf2", - "rand_core 0.6.4", - "ripemd", - "sha2 0.10.7", - "subtle 2.4.1", - "zeroize", -] - -[[package]] -name = "bip39" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" -dependencies = [ - "bitcoin_hashes", - "rand 0.8.5", - "rand_core 0.6.4", - "serde", - "unicode-normalization", - "zeroize", -] - -[[package]] -name = "bitcoin_hashes" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "blake2" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330" -dependencies = [ - "byte-tools", - "crypto-mac 0.7.0", - "digest 0.8.1", - "opaque-debug 0.2.3", -] - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "blake3" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "199c42ab6972d92c9f8995f086273d25c42fc0f7b2a1fcefba465c1352d25ba5" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if 1.0.0", - "constant_time_eq", - "digest 0.10.7", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "bls12_381" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54757888b09a69be70b5ec303e382a74227392086ba808cb01eeca29233a2397" -dependencies = [ - "digest 0.9.0", - "ff 0.10.1", - "group 0.10.0", - "pairing 0.20.0", - "rand_core 0.6.4", - "subtle 2.4.1", -] - -[[package]] -name = "bls12_381" -version = "0.6.0" -source = "git+https://github.com/jstuczyn/bls12_381?branch=gt-serialisation#10fb6f700bfda17c8475af3bfd31e3fec15f2278" -dependencies = [ - "digest 0.9.0", - "ff 0.11.1", - "group 0.11.0", - "pairing 0.21.0", - "rand_core 0.6.4", - "subtle 2.4.1", - "zeroize", -] - -[[package]] -name = "bnum" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "845141a4fade3f790628b7daaaa298a25b204fb28907eb54febe5142db6ce653" - -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - -[[package]] -name = "bs58" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" -dependencies = [ - "sha2 0.10.7", -] - -[[package]] -name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" -dependencies = [ - "serde", -] - -[[package]] -name = "cc" -version = "1.0.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" -dependencies = [ - "jobserver", - "libc", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chacha" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf3c081b5fba1e5615640aae998e0fbd10c24cbd897ee39ed754a77601a4862" -dependencies = [ - "byteorder", - "keystream", -] - -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if 1.0.0", - "cipher 0.4.4", - "cpufeatures", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20", - "cipher 0.4.4", - "poly1305", - "zeroize", -] - -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", - "zeroize", -] - -[[package]] -name = "clap" -version = "4.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" -dependencies = [ - "clap_builder", - "clap_derive", - "once_cell", -] - -[[package]] -name = "clap_builder" -version = "4.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_complete" -version = "4.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc443334c81a804575546c5a8a79b4913b50e28d69232903604cada1de817ce" -dependencies = [ - "clap", -] - -[[package]] -name = "clap_complete_fig" -version = "4.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fee1d30a51305a6c2ed3fc5709be3c8af626c9c958e04dd9ae94e27bcbce9f" -dependencies = [ - "clap", - "clap_complete", -] - -[[package]] -name = "clap_derive" -version = "4.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "clap_lex" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" - -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - -[[package]] -name = "colored" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" -dependencies = [ - "is-terminal", - "lazy_static", - "windows-sys", -] - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen", -] - -[[package]] -name = "const-oid" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" - -[[package]] -name = "constant_time_eq" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "cosmos-sdk-proto" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73c9d2043a9e617b0d602fbc0a0ecd621568edbf3a9774890a6d562389bd8e1c" -dependencies = [ - "prost", - "prost-types", - "tendermint-proto", -] - -[[package]] -name = "cosmrs" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af13955d6f356272e6def9ff5e2450a7650df536d8934f47052a20c76513d2f6" -dependencies = [ - "bip32", - "cosmos-sdk-proto", - "ecdsa 0.16.8", - "eyre", - "getrandom 0.2.10", - "k256 0.13.1", - "rand_core 0.6.4", - "serde", - "serde_json", - "subtle-encoding", - "tendermint", - "tendermint-rpc", - "thiserror", -] - -[[package]] -name = "cosmwasm-crypto" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e272708a9745dad8b591ef8a718571512130f2b39b33e3d7a27c558e3069394" -dependencies = [ - "digest 0.10.7", - "ed25519-zebra", - "k256 0.11.6", - "rand_core 0.6.4", - "thiserror", -] - -[[package]] -name = "cosmwasm-derive" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "296db6a3caca5283425ae0cf347f4e46999ba3f6620dbea8939a0e00347831ce" -dependencies = [ - "syn 1.0.109", -] - -[[package]] -name = "cosmwasm-schema" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6b2fb76758ef59cddc77f2e2ae91c22f77da49037e9f182e9c2833f0e959b1" -dependencies = [ - "cosmwasm-schema-derive", - "schemars", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "cosmwasm-schema-derive" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bfa39422f0d9f1c9a6fd3711573258495314dfa3aae738ea825ecd9964bc659" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "cosmwasm-std" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f6dc2ee23313add5ecacc3ccac217b9967ad9d2d11bd56e5da6aa65a9da6138" -dependencies = [ - "base64 0.13.1", - "bnum", - "cosmwasm-crypto", - "cosmwasm-derive", - "derivative", - "forward_ref", - "hex", - "schemars", - "serde", - "serde-json-wasm", - "sha2 0.10.7", - "thiserror", -] - -[[package]] -name = "cpufeatures" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" -dependencies = [ - "crc-catalog 1.1.1", -] - -[[package]] -name = "crc" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" -dependencies = [ - "crc-catalog 2.2.0", -] - -[[package]] -name = "crc-catalog" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" - -[[package]] -name = "crc-catalog" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" -dependencies = [ - "autocfg", - "cfg-if 1.0.0", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "crypto-bigint" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" -dependencies = [ - "generic-array 0.14.7", - "rand_core 0.6.4", - "subtle 2.4.1", - "zeroize", -] - -[[package]] -name = "crypto-bigint" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15" -dependencies = [ - "generic-array 0.14.7", - "rand_core 0.6.4", - "subtle 2.4.1", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array 0.14.7", - "rand_core 0.6.4", - "typenum", -] - -[[package]] -name = "crypto-mac" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -dependencies = [ - "generic-array 0.12.4", - "subtle 1.0.0", -] - -[[package]] -name = "crypto-mac" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array 0.14.7", - "subtle 2.4.1", -] - -[[package]] -name = "ct-logs" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" -dependencies = [ - "sct 0.6.1", -] - -[[package]] -name = "ctr" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" -dependencies = [ - "cipher 0.3.0", -] - -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher 0.4.4", -] - -[[package]] -name = "curve25519-dalek" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "serde", - "subtle 2.4.1", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-ng" -version = "4.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.6.4", - "subtle-ng", - "zeroize", -] - -[[package]] -name = "cw-controllers" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d8edce4b78785f36413f67387e4be7d0cb7d032b5d4164bcc024f9c3f3f2ea" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus", - "cw-utils", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw-storage-plus" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f0e92a069d62067f3472c62e30adedb4cab1754725c0f2a682b3128d2bf3c79" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - -[[package]] -name = "cw-utils" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c80e93d1deccb8588db03945016a292c3c631e6325d349ebb35d2db6f4f946f7" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw2", - "schemars", - "semver 1.0.18", - "serde", - "thiserror", -] - -[[package]] -name = "cw2" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ac2dc7a55ad64173ca1e0a46697c31b7a5c51342f55a1e84a724da4eb99908" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw20" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "011c45920f8200bd5d32d4fe52502506f64f2f75651ab408054d4cfc75ca3a9b" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-utils", - "schemars", - "serde", -] - -[[package]] -name = "cw3" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171af3d9127de6805a7dd819fb070c7d2f6c3ea85f4193f42cef259f0a7f33d5" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-utils", - "cw20", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "cw4" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a398696307efadaaa2d0850076f865fa706c959d493cb4203314f72be6b77a64" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus", - "schemars", - "serde", -] - -[[package]] -name = "dashmap" -version = "5.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" -dependencies = [ - "cfg-if 1.0.0", - "hashbrown 0.14.0", - "lock_api", - "once_cell", - "parking_lot_core 0.9.8", -] - -[[package]] -name = "der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "der" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929" - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "const-oid", - "crypto-common", - "subtle 2.4.1", -] - -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys 0.3.7", -] - -[[package]] -name = "dirs" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" -dependencies = [ - "dirs-sys 0.4.1", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys", -] - -[[package]] -name = "dotenv" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" - -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "dyn-clone" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "304e6508efa593091e97a9abbc10f90aa7ca635b6d2784feff3c89d41dd12272" - -[[package]] -name = "ecdsa" -version = "0.14.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der 0.6.1", - "elliptic-curve 0.12.3", - "rfc6979 0.3.1", - "signature 1.6.4", -] - -[[package]] -name = "ecdsa" -version = "0.16.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" -dependencies = [ - "der 0.7.8", - "digest 0.10.7", - "elliptic-curve 0.13.5", - "rfc6979 0.4.0", - "signature 2.1.0", - "spki 0.7.2", -] - -[[package]] -name = "ed25519" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" -dependencies = [ - "serde", - "signature 1.6.4", -] - -[[package]] -name = "ed25519" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60f6d271ca33075c88028be6f04d502853d63a5ece419d269c15315d4fc1cf1d" -dependencies = [ - "pkcs8 0.10.2", - "signature 2.1.0", -] - -[[package]] -name = "ed25519-consensus" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c8465edc8ee7436ffea81d21a019b16676ee3db267aa8d5a8d729581ecf998b" -dependencies = [ - "curve25519-dalek-ng", - "hex", - "rand_core 0.6.4", - "sha2 0.9.9", - "zeroize", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -dependencies = [ - "curve25519-dalek", - "ed25519 1.5.3", - "rand 0.7.3", - "serde", - "serde_bytes", - "sha2 0.9.9", - "zeroize", -] - -[[package]] -name = "ed25519-zebra" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" -dependencies = [ - "curve25519-dalek", - "hashbrown 0.12.3", - "hex", - "rand_core 0.6.4", - "serde", - "sha2 0.9.9", - "zeroize", -] - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "elliptic-curve" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" -dependencies = [ - "base16ct 0.1.1", - "crypto-bigint 0.4.9", - "der 0.6.1", - "digest 0.10.7", - "ff 0.12.1", - "generic-array 0.14.7", - "group 0.12.1", - "pkcs8 0.9.0", - "rand_core 0.6.4", - "sec1 0.3.0", - "subtle 2.4.1", - "zeroize", -] - -[[package]] -name = "elliptic-curve" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" -dependencies = [ - "base16ct 0.2.0", - "crypto-bigint 0.5.2", - "digest 0.10.7", - "ff 0.13.0", - "generic-array 0.14.7", - "group 0.13.0", - "pkcs8 0.10.2", - "rand_core 0.6.4", - "sec1 0.7.3", - "subtle 2.4.1", - "zeroize", -] - -[[package]] -name = "encoding_rs" -version = "0.8.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "enum-iterator" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a0ac4aeb3a18f92eaf09c6bb9b3ac30ff61ca95514fc58cbead1c9a6bf5401" -dependencies = [ - "enum-iterator-derive", -] - -[[package]] -name = "enum-iterator-derive" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "atty", - "humantime 1.3.0", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "eyre" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fastrand" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" - -[[package]] -name = "ff" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f" -dependencies = [ - "rand_core 0.6.4", - "subtle 2.4.1", -] - -[[package]] -name = "ff" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" -dependencies = [ - "rand_core 0.6.4", - "subtle 2.4.1", -] - -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" -dependencies = [ - "rand_core 0.6.4", - "subtle 2.4.1", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core 0.6.4", - "subtle 2.4.1", -] - -[[package]] -name = "flate2" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "flex-error" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" -dependencies = [ - "eyre", - "paste", -] - -[[package]] -name = "flume" -version = "0.10.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" -dependencies = [ - "futures-core", - "futures-sink", - "pin-project", - "spin 0.9.8", -] - -[[package]] -name = "fnv" -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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "forward_ref" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-executor" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-intrusive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" -dependencies = [ - "futures-core", - "lock_api", - "parking_lot 0.11.2", -] - -[[package]] -name = "futures-io" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" - -[[package]] -name = "futures-macro" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - -[[package]] -name = "futures-task" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" - -[[package]] -name = "futures-util" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "serde", - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getset" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ghash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" -dependencies = [ - "opaque-debug 0.3.0", - "polyval", -] - -[[package]] -name = "gimli" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" - -[[package]] -name = "git2" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0155506aab710a86160ddb504a480d2964d7ab5b9e62419be69e0032bc5931c" -dependencies = [ - "bitflags 1.3.2", - "libc", - "libgit2-sys", - "log", - "url", -] - -[[package]] -name = "gloo-timers" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "group" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912" -dependencies = [ - "byteorder", - "ff 0.10.1", - "rand_core 0.6.4", - "subtle 2.4.1", -] - -[[package]] -name = "group" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" -dependencies = [ - "byteorder", - "ff 0.11.1", - "rand_core 0.6.4", - "subtle 2.4.1", -] - -[[package]] -name = "group" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" -dependencies = [ - "ff 0.12.1", - "rand_core 0.6.4", - "subtle 2.4.1", -] - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff 0.13.0", - "rand_core 0.6.4", - "subtle 2.4.1", -] - -[[package]] -name = "h2" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap 1.9.3", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "handlebars" -version = "3.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4498fc115fa7d34de968184e473529abb40eeb6be8bc5f7faba3d08c316cb3e3" -dependencies = [ - "log", - "pest", - "pest_derive", - "quick-error 2.0.1", - "serde", - "serde_json", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash 0.7.6", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.6", -] - -[[package]] -name = "hashbrown" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" -dependencies = [ - "ahash 0.8.3", - "allocator-api2", -] - -[[package]] -name = "hashlink" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" -dependencies = [ - "hashbrown 0.11.2", -] - -[[package]] -name = "hashlink" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f" -dependencies = [ - "hashbrown 0.14.0", -] - -[[package]] -name = "headers" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" -dependencies = [ - "base64 0.13.1", - "bitflags 1.3.2", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hex-literal" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" - -[[package]] -name = "hkdf" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01706d578d5c281058480e673ae4086a9f4710d8df1ad80a5b03e39ece5f886b" -dependencies = [ - "digest 0.9.0", - "hmac 0.11.0", -] - -[[package]] -name = "hkdf" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" -dependencies = [ - "hmac 0.12.1", -] - -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac 0.11.1", - "digest 0.9.0", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "http" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "humantime" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error 1.2.3", -] - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "humantime-serde" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c" -dependencies = [ - "humantime 2.1.0", - "serde", -] - -[[package]] -name = "hyper" -version = "0.14.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.4.9", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-proxy" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca815a891b24fdfb243fa3239c86154392b0953ee584aa1a2a1f66d20cbe75cc" -dependencies = [ - "bytes", - "futures", - "headers", - "http", - "hyper", - "hyper-rustls", - "rustls-native-certs", - "tokio", - "tokio-rustls 0.22.0", - "tower-service", - "webpki 0.21.4", -] - -[[package]] -name = "hyper-rustls" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" -dependencies = [ - "ct-logs", - "futures-util", - "hyper", - "log", - "rustls 0.19.1", - "rustls-native-certs", - "tokio", - "tokio-rustls 0.22.0", - "webpki 0.21.4", - "webpki-roots 0.21.1", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "indexed_db_futures" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfbcff6ae46750b15cc594bfd277b188cbddcfdc1817848f97f03f26f8625b9e" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "uuid 1.4.1", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" -dependencies = [ - "equivalent", - "hashbrown 0.14.0", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "input_buffer" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413" -dependencies = [ - "bytes", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "ipnet" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" - -[[package]] -name = "is-terminal" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi 0.3.2", - "rustix", - "windows-sys", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "jobserver" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "k256" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" -dependencies = [ - "cfg-if 1.0.0", - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", - "sha2 0.10.7", -] - -[[package]] -name = "k256" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" -dependencies = [ - "cfg-if 1.0.0", - "ecdsa 0.16.8", - "elliptic-curve 0.13.5", - "once_cell", - "sha2 0.10.7", - "signature 2.1.0", -] - -[[package]] -name = "keystream" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33070833c9ee02266356de0c43f723152bd38bd96ddf52c82b3af10c9138b28" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - -[[package]] -name = "libgit2-sys" -version = "0.13.5+1.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e5ea06c26926f1002dd553fded6cfcdc9784c1f60feeb58368b4d9b07b6dba" -dependencies = [ - "cc", - "libc", - "libz-sys", - "pkg-config", -] - -[[package]] -name = "libm" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" - -[[package]] -name = "libsqlite3-sys" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "libz-sys" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" - -[[package]] -name = "lioness" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae926706ba42c425c9457121178330d75e273df2e82e28b758faf3de3a9acb9" -dependencies = [ - "arrayref", - "blake2 0.8.1", - "chacha", - "keystream", -] - -[[package]] -name = "lock_api" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memory_units" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", -] - -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num-traits" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.2", - "libc", -] - -[[package]] -name = "nym-api-requests" -version = "0.1.0" -dependencies = [ - "bs58 0.4.0", - "cosmrs", - "cosmwasm-std", - "getset", - "nym-coconut-interface", - "nym-mixnet-contract-common", - "schemars", - "serde", -] - -[[package]] -name = "nym-bandwidth-controller" -version = "0.1.0" -dependencies = [ - "bip39", - "nym-coconut-interface", - "nym-credential-storage", - "nym-credentials", - "nym-crypto", - "nym-network-defaults", - "nym-validator-client", - "rand 0.7.3", - "thiserror", - "url", -] - -[[package]] -name = "nym-bin-common" -version = "0.6.0" -dependencies = [ - "atty", - "clap", - "clap_complete", - "clap_complete_fig", - "log", - "pretty_env_logger", - "semver 0.11.0", - "serde", - "vergen", -] - -[[package]] -name = "nym-client-core" -version = "1.1.15" -dependencies = [ - "async-trait", - "base64 0.21.2", - "cfg-if 1.0.0", - "dashmap", - "dirs 4.0.0", - "futures", - "gloo-timers", - "humantime-serde", - "log", - "nym-bandwidth-controller", - "nym-config", - "nym-credential-storage", - "nym-crypto", - "nym-explorer-client", - "nym-gateway-client", - "nym-gateway-requests", - "nym-network-defaults", - "nym-nonexhaustive-delayqueue", - "nym-pemstore", - "nym-sphinx", - "nym-task", - "nym-topology", - "nym-validator-client", - "rand 0.7.3", - "reqwest", - "serde", - "serde_json", - "sha2 0.10.7", - "sqlx 0.6.3", - "tap", - "thiserror", - "time", - "tokio", - "tokio-stream", - "tokio-tungstenite", - "tungstenite", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-utils", - "wasmtimer", - "zeroize", -] - -[[package]] -name = "nym-client-wasm" -version = "1.1.1" -dependencies = [ - "anyhow", - "async-trait", - "bs58 0.4.0", - "console_error_panic_hook", - "futures", - "js-sys", - "nym-bandwidth-controller", - "nym-client-core", - "nym-coconut-interface", - "nym-credential-storage", - "nym-credentials", - "nym-crypto", - "nym-gateway-client", - "nym-node-tester-utils", - "nym-sphinx", - "nym-sphinx-acknowledgements", - "nym-task", - "nym-topology", - "nym-validator-client", - "rand 0.7.3", - "serde", - "serde-wasm-bindgen", - "serde_json", - "thiserror", - "tokio", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-bindgen-test", - "wasm-utils", - "wasmtimer", - "wee_alloc", - "zeroize", -] - -[[package]] -name = "nym-coconut" -version = "0.5.0" -dependencies = [ - "bls12_381 0.6.0", - "bs58 0.4.0", - "digest 0.9.0", - "ff 0.11.1", - "getrandom 0.2.10", - "group 0.11.0", - "itertools", - "nym-dkg", - "nym-pemstore", - "rand 0.8.5", - "serde", - "serde_derive", - "sha2 0.9.9", - "thiserror", -] - -[[package]] -name = "nym-coconut-bandwidth-contract-common" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "nym-multisig-contract-common", -] - -[[package]] -name = "nym-coconut-dkg-common" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-utils", - "nym-contracts-common", - "nym-multisig-contract-common", -] - -[[package]] -name = "nym-coconut-interface" -version = "0.1.0" -dependencies = [ - "bs58 0.4.0", - "getset", - "nym-coconut", - "serde", - "thiserror", -] - -[[package]] -name = "nym-config" -version = "0.1.0" -dependencies = [ - "dirs 5.0.1", - "handlebars", - "log", - "nym-network-defaults", - "serde", - "toml 0.7.6", - "url", -] - -[[package]] -name = "nym-contracts-common" -version = "0.5.0" -dependencies = [ - "bs58 0.4.0", - "cosmwasm-schema", - "cosmwasm-std", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "nym-credential-storage" -version = "0.1.0" -dependencies = [ - "async-trait", - "log", - "sqlx 0.5.13", - "thiserror", - "tokio", -] - -[[package]] -name = "nym-credentials" -version = "0.1.0" -dependencies = [ - "bls12_381 0.5.0", - "cosmrs", - "log", - "nym-api-requests", - "nym-coconut-interface", - "nym-crypto", - "nym-validator-client", - "thiserror", -] - -[[package]] -name = "nym-crypto" -version = "0.4.0" -dependencies = [ - "aes 0.8.3", - "blake3", - "bs58 0.4.0", - "cipher 0.4.4", - "ctr 0.9.2", - "digest 0.10.7", - "ed25519-dalek", - "generic-array 0.14.7", - "hkdf 0.12.3", - "hmac 0.12.1", - "nym-pemstore", - "nym-sphinx-types", - "rand 0.7.3", - "serde", - "serde_bytes", - "subtle-encoding", - "thiserror", - "x25519-dalek", - "zeroize", -] - -[[package]] -name = "nym-dkg" -version = "0.1.0" -dependencies = [ - "bitvec", - "bls12_381 0.6.0", - "bs58 0.4.0", - "ff 0.11.1", - "group 0.11.0", - "lazy_static", - "nym-pemstore", - "rand 0.8.5", - "rand_chacha 0.3.1", - "rand_core 0.6.4", - "serde", - "serde_derive", - "sha2 0.9.9", - "thiserror", - "zeroize", -] - -[[package]] -name = "nym-ephemera-common" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-utils", - "nym-contracts-common", -] - -[[package]] -name = "nym-explorer-api-requests" -version = "0.1.0" -dependencies = [ - "nym-api-requests", - "nym-contracts-common", - "nym-mixnet-contract-common", - "schemars", - "serde", -] - -[[package]] -name = "nym-explorer-client" -version = "0.1.0" -dependencies = [ - "log", - "nym-explorer-api-requests", - "reqwest", - "serde", - "thiserror", - "url", -] - -[[package]] -name = "nym-gateway-client" -version = "0.1.0" -dependencies = [ - "futures", - "getrandom 0.2.10", - "log", - "nym-bandwidth-controller", - "nym-coconut-interface", - "nym-credential-storage", - "nym-crypto", - "nym-gateway-requests", - "nym-network-defaults", - "nym-pemstore", - "nym-sphinx", - "nym-task", - "nym-validator-client", - "rand 0.7.3", - "serde", - "thiserror", - "tokio", - "tokio-stream", - "tokio-tungstenite", - "tungstenite", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-utils", - "wasmtimer", -] - -[[package]] -name = "nym-gateway-requests" -version = "0.1.0" -dependencies = [ - "bs58 0.4.0", - "futures", - "generic-array 0.14.7", - "log", - "nym-coconut-interface", - "nym-credentials", - "nym-crypto", - "nym-pemstore", - "nym-sphinx", - "rand 0.7.3", - "serde", - "serde_json", - "thiserror", - "tungstenite", - "zeroize", -] - -[[package]] -name = "nym-group-contract-common" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema", - "cw-controllers", - "cw4", - "schemars", - "serde", -] - -[[package]] -name = "nym-mixnet-contract-common" -version = "0.6.0" -dependencies = [ - "bs58 0.4.0", - "cosmwasm-schema", - "cosmwasm-std", - "humantime-serde", - "log", - "nym-contracts-common", - "schemars", - "serde", - "serde-json-wasm", - "serde_repr", - "thiserror", - "time", -] - -[[package]] -name = "nym-multisig-contract-common" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus", - "cw-utils", - "cw3", - "cw4", - "schemars", - "serde", - "thiserror", -] - -[[package]] -name = "nym-name-service-common" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-controllers", - "cw-utils", - "nym-contracts-common", - "serde", - "thiserror", -] - -[[package]] -name = "nym-network-defaults" -version = "0.1.0" -dependencies = [ - "cfg-if 1.0.0", - "dotenvy", - "hex-literal", - "once_cell", - "schemars", - "serde", - "thiserror", - "url", -] - -[[package]] -name = "nym-node-tester-utils" -version = "0.1.0" -dependencies = [ - "futures", - "log", - "nym-crypto", - "nym-sphinx", - "nym-sphinx-params", - "nym-task", - "nym-topology", - "rand 0.7.3", - "serde", - "serde_json", - "thiserror", - "tokio", - "wasm-utils", -] - -[[package]] -name = "nym-nonexhaustive-delayqueue" -version = "0.1.0" -dependencies = [ - "tokio", - "tokio-stream", - "tokio-util", - "wasmtimer", -] - -[[package]] -name = "nym-outfox" -version = "0.1.0" -dependencies = [ - "blake3", - "chacha20", - "chacha20poly1305", - "curve25519-dalek", - "getrandom 0.2.10", - "log", - "rand 0.7.3", - "rayon", - "sphinx-packet", - "thiserror", - "zeroize", -] - -[[package]] -name = "nym-pemstore" -version = "0.3.0" -dependencies = [ - "pem", -] - -[[package]] -name = "nym-service-provider-directory-common" -version = "0.1.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-controllers", - "cw-utils", - "nym-contracts-common", - "thiserror", -] - -[[package]] -name = "nym-sphinx" -version = "0.1.0" -dependencies = [ - "log", - "nym-crypto", - "nym-sphinx-acknowledgements", - "nym-sphinx-addressing", - "nym-sphinx-anonymous-replies", - "nym-sphinx-chunking", - "nym-sphinx-cover", - "nym-sphinx-forwarding", - "nym-sphinx-framing", - "nym-sphinx-params", - "nym-sphinx-routing", - "nym-sphinx-types", - "nym-topology", - "rand 0.7.3", - "rand_distr", - "thiserror", - "tokio", -] - -[[package]] -name = "nym-sphinx-acknowledgements" -version = "0.1.0" -dependencies = [ - "generic-array 0.14.7", - "nym-crypto", - "nym-pemstore", - "nym-sphinx-addressing", - "nym-sphinx-params", - "nym-sphinx-routing", - "nym-sphinx-types", - "nym-topology", - "rand 0.7.3", - "serde", - "thiserror", - "zeroize", -] - -[[package]] -name = "nym-sphinx-addressing" -version = "0.1.0" -dependencies = [ - "nym-crypto", - "nym-sphinx-types", - "serde", - "thiserror", -] - -[[package]] -name = "nym-sphinx-anonymous-replies" -version = "0.1.0" -dependencies = [ - "bs58 0.4.0", - "nym-crypto", - "nym-sphinx-addressing", - "nym-sphinx-params", - "nym-sphinx-routing", - "nym-sphinx-types", - "nym-topology", - "rand 0.7.3", - "serde", - "thiserror", - "wasm-bindgen", -] - -[[package]] -name = "nym-sphinx-chunking" -version = "0.1.0" -dependencies = [ - "log", - "nym-sphinx-addressing", - "nym-sphinx-params", - "nym-sphinx-types", - "rand 0.7.3", - "thiserror", -] - -[[package]] -name = "nym-sphinx-cover" -version = "0.1.0" -dependencies = [ - "nym-crypto", - "nym-sphinx-acknowledgements", - "nym-sphinx-addressing", - "nym-sphinx-chunking", - "nym-sphinx-forwarding", - "nym-sphinx-params", - "nym-sphinx-routing", - "nym-sphinx-types", - "nym-topology", - "rand 0.7.3", - "thiserror", -] - -[[package]] -name = "nym-sphinx-forwarding" -version = "0.1.0" -dependencies = [ - "nym-outfox", - "nym-sphinx-addressing", - "nym-sphinx-params", - "nym-sphinx-types", - "thiserror", -] - -[[package]] -name = "nym-sphinx-framing" -version = "0.1.0" -dependencies = [ - "bytes", - "nym-sphinx-params", - "nym-sphinx-types", - "thiserror", - "tokio-util", -] - -[[package]] -name = "nym-sphinx-params" -version = "0.1.0" -dependencies = [ - "nym-crypto", - "nym-sphinx-types", - "serde", - "thiserror", -] - -[[package]] -name = "nym-sphinx-routing" -version = "0.1.0" -dependencies = [ - "nym-sphinx-addressing", - "nym-sphinx-types", - "thiserror", -] - -[[package]] -name = "nym-sphinx-types" -version = "0.2.0" -dependencies = [ - "nym-outfox", - "sphinx-packet", - "thiserror", -] - -[[package]] -name = "nym-store-cipher" -version = "0.1.0" -dependencies = [ - "aes-gcm", - "argon2", - "generic-array 0.14.7", - "getrandom 0.2.10", - "rand 0.8.5", - "serde", - "serde_json", - "thiserror", - "zeroize", -] - -[[package]] -name = "nym-task" -version = "0.1.0" -dependencies = [ - "futures", - "log", - "thiserror", - "tokio", - "wasm-bindgen", - "wasm-bindgen-futures", -] - -[[package]] -name = "nym-topology" -version = "0.1.0" -dependencies = [ - "async-trait", - "bs58 0.4.0", - "log", - "nym-bin-common", - "nym-crypto", - "nym-mixnet-contract-common", - "nym-sphinx-addressing", - "nym-sphinx-routing", - "nym-sphinx-types", - "rand 0.7.3", - "thiserror", -] - -[[package]] -name = "nym-validator-client" -version = "0.1.0" -dependencies = [ - "async-trait", - "base64 0.13.1", - "bip39", - "colored", - "cosmrs", - "cosmwasm-std", - "cw-controllers", - "cw-utils", - "cw2", - "cw3", - "cw4", - "eyre", - "flate2", - "futures", - "itertools", - "log", - "nym-api-requests", - "nym-coconut-bandwidth-contract-common", - "nym-coconut-dkg-common", - "nym-coconut-interface", - "nym-config", - "nym-contracts-common", - "nym-ephemera-common", - "nym-group-contract-common", - "nym-mixnet-contract-common", - "nym-multisig-contract-common", - "nym-name-service-common", - "nym-network-defaults", - "nym-service-provider-directory-common", - "nym-vesting-contract-common", - "openssl", - "prost", - "reqwest", - "serde", - "serde_json", - "sha2 0.9.9", - "tendermint-rpc", - "thiserror", - "tokio", - "url", - "wasmtimer", - "zeroize", -] - -[[package]] -name = "nym-vesting-contract-common" -version = "0.7.0" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "nym-contracts-common", - "nym-mixnet-contract-common", - "serde", - "thiserror", -] - -[[package]] -name = "object" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "openssl" -version = "0.10.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e" -dependencies = [ - "bitflags 1.3.2", - "cfg-if 1.0.0", - "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.28", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-src" -version = "111.27.0+1.1.1v" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e8f197c82d7511c5b014030c9b1efeda40d7d5f99d23b4ceed3524a5e63f02" -dependencies = [ - "cc", -] - -[[package]] -name = "openssl-sys" -version = "0.9.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" -dependencies = [ - "cc", - "libc", - "openssl-src", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "pairing" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de9d09263c9966e8196fe0380c9dbbc7ea114b5cf371ba29004bc1f9c6db7f3" -dependencies = [ - "group 0.10.0", -] - -[[package]] -name = "pairing" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2e415e349a3006dd7d9482cdab1c980a845bed1377777d768cb693a44540b42" -dependencies = [ - "group 0.11.0", -] - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.8", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall 0.3.5", - "smallvec", - "windows-targets", -] - -[[package]] -name = "password-hash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle 2.4.1", -] - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest 0.10.7", - "hmac 0.12.1", -] - -[[package]] -name = "peg" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c0b841ea54f523f7aa556956fbd293bcbe06f2e67d2eb732b7278aaf1d166a" -dependencies = [ - "peg-macros", - "peg-runtime", -] - -[[package]] -name = "peg-macros" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c" -dependencies = [ - "peg-runtime", - "proc-macro2", - "quote", -] - -[[package]] -name = "peg-runtime" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c719dcf55f09a3a7e764c6649ab594c18a177e3599c467983cdf644bfc0a4088" - -[[package]] -name = "pem" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" -dependencies = [ - "base64 0.13.1", - "once_cell", - "regex", -] - -[[package]] -name = "percent-encoding" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" - -[[package]] -name = "pest" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1acb4a4365a13f749a93f1a094a7805e5cfa0955373a9de860d962eaa3a5fe5a" -dependencies = [ - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "666d00490d4ac815001da55838c500eafb0320019bbaa44444137c48b443a853" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ca01446f50dbda87c1786af8770d535423fa8a53aec03b8f4e3d7eb10e0929" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "pest_meta" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56af0a30af74d0445c0bf6d9d051c979b516a1a5af790d251daee76005420a48" -dependencies = [ - "once_cell", - "pest", - "sha2 0.10.7", -] - -[[package]] -name = "pin-project" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs8" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der 0.6.1", - "spki 0.6.0", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der 0.7.8", - "spki 0.7.2", -] - -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug 0.3.0", - "universal-hash", -] - -[[package]] -name = "polyval" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "opaque-debug 0.3.0", - "universal-hash", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "pretty_env_logger" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" -dependencies = [ - "env_logger", - "log", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prost" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-derive" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "prost-types" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" -dependencies = [ - "prost", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - -[[package]] -name = "quote" -version = "1.0.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.10", -] - -[[package]] -name = "rand_distr" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9532ada3929fb8b2e9dbe28d1e06c9b2cc65813f074fcb6bd5fbefeff9d56" -dependencies = [ - "num-traits", - "rand 0.7.3", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rayon" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_users" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" - -[[package]] -name = "reqwest" -version = "0.11.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" -dependencies = [ - "base64 0.21.2", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - -[[package]] -name = "rfc6979" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" -dependencies = [ - "crypto-bigint 0.4.9", - "hmac 0.12.1", - "zeroize", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac 0.12.1", - "subtle 2.4.1", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted", - "web-sys", - "winapi", -] - -[[package]] -name = "ripemd" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.18", -] - -[[package]] -name = "rustix" -version = "0.38.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" -dependencies = [ - "bitflags 2.4.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "rustls" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" -dependencies = [ - "base64 0.13.1", - "log", - "ring", - "sct 0.6.1", - "webpki 0.21.4", -] - -[[package]] -name = "rustls" -version = "0.20.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" -dependencies = [ - "log", - "ring", - "sct 0.7.0", - "webpki 0.22.0", -] - -[[package]] -name = "rustls-native-certs" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" -dependencies = [ - "openssl-probe", - "rustls 0.19.1", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" -dependencies = [ - "base64 0.21.2", -] - -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "schemars" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c613288622e5f0c3fdc5dbd4db1c5fbe752746b1d1a56a0630b78fd00de44f" -dependencies = [ - "dyn-clone", - "indexmap 1.9.3", - "schemars_derive", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109da1e6b197438deb6db99952990c7f959572794b80ff93707d55a232545e7c" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 1.0.109", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sct" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "sec1" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" -dependencies = [ - "base16ct 0.1.1", - "der 0.6.1", - "generic-array 0.14.7", - "pkcs8 0.9.0", - "subtle 2.4.1", - "zeroize", -] - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct 0.2.0", - "der 0.7.8", - "generic-array 0.14.7", - "pkcs8 0.10.2", - "subtle 2.4.1", - "zeroize", -] - -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" - -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - -[[package]] -name = "serde" -version = "1.0.183" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde-json-wasm" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15bee9b04dd165c3f4e142628982ddde884c2022a89e8ddf99c4829bf2c3a58" -dependencies = [ - "serde", -] - -[[package]] -name = "serde-wasm-bindgen" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" -dependencies = [ - "js-sys", - "serde", - "wasm-bindgen", -] - -[[package]] -name = "serde_bytes" -version = "0.11.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.183" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "serde_derive_internals" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "serde_json" -version = "1.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_repr" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "serde_spanned" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug 0.3.0", -] - -[[package]] -name = "sha1" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug 0.3.0", -] - -[[package]] -name = "sha2" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - -[[package]] -name = "signature" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - -[[package]] -name = "slab" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" - -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "sphinx-packet" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc43eda802856ee82a7555c7b75ceb9e07451741c7a2f5f23d036020e01189d4" -dependencies = [ - "aes 0.7.5", - "arrayref", - "blake2 0.8.1", - "bs58 0.4.0", - "byteorder", - "chacha", - "curve25519-dalek", - "digest 0.9.0", - "hkdf 0.11.0", - "hmac 0.11.0", - "lioness", - "log", - "rand 0.7.3", - "rand_distr", - "sha2 0.9.9", - "subtle 2.4.1", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - -[[package]] -name = "spki" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" -dependencies = [ - "base64ct", - "der 0.6.1", -] - -[[package]] -name = "spki" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" -dependencies = [ - "base64ct", - "der 0.7.8", -] - -[[package]] -name = "sqlformat" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" -dependencies = [ - "itertools", - "nom", - "unicode_categories", -] - -[[package]] -name = "sqlformat" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c12bc9199d1db8234678b7051747c07f517cdcf019262d1847b94ec8b1aee3e" -dependencies = [ - "itertools", - "nom", - "unicode_categories", -] - -[[package]] -name = "sqlx" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "551873805652ba0d912fec5bbb0f8b4cdd96baf8e2ebf5970e5671092966019b" -dependencies = [ - "sqlx-core 0.5.13", - "sqlx-macros 0.5.13", -] - -[[package]] -name = "sqlx" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188" -dependencies = [ - "sqlx-core 0.6.3", - "sqlx-macros 0.6.3", -] - -[[package]] -name = "sqlx-core" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48c61941ccf5ddcada342cd59e3e5173b007c509e1e8e990dafc830294d9dc5" -dependencies = [ - "ahash 0.7.6", - "atoi 0.4.0", - "bitflags 1.3.2", - "byteorder", - "bytes", - "crc 2.1.0", - "crossbeam-queue", - "either", - "event-listener", - "flume", - "futures-channel", - "futures-core", - "futures-executor", - "futures-intrusive", - "futures-util", - "hashlink 0.7.0", - "hex", - "indexmap 1.9.3", - "itoa", - "libc", - "libsqlite3-sys", - "log", - "memchr", - "once_cell", - "paste", - "percent-encoding", - "rustls 0.19.1", - "sha2 0.10.7", - "smallvec", - "sqlformat 0.1.8", - "sqlx-rt 0.5.13", - "stringprep", - "thiserror", - "tokio-stream", - "url", - "webpki 0.21.4", - "webpki-roots 0.21.1", -] - -[[package]] -name = "sqlx-core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" -dependencies = [ - "ahash 0.7.6", - "atoi 1.0.0", - "bitflags 1.3.2", - "byteorder", - "bytes", - "crc 3.0.1", - "crossbeam-queue", - "dotenvy", - "either", - "event-listener", - "flume", - "futures-channel", - "futures-core", - "futures-executor", - "futures-intrusive", - "futures-util", - "hashlink 0.8.3", - "hex", - "indexmap 1.9.3", - "itoa", - "libc", - "libsqlite3-sys", - "log", - "memchr", - "once_cell", - "paste", - "percent-encoding", - "rustls 0.20.8", - "rustls-pemfile", - "sha2 0.10.7", - "smallvec", - "sqlformat 0.2.1", - "sqlx-rt 0.6.3", - "stringprep", - "thiserror", - "tokio-stream", - "url", - "webpki-roots 0.22.6", -] - -[[package]] -name = "sqlx-macros" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0fba2b0cae21fc00fe6046f8baa4c7fcb49e379f0f592b04696607f69ed2e1" -dependencies = [ - "dotenv", - "either", - "heck", - "once_cell", - "proc-macro2", - "quote", - "sha2 0.10.7", - "sqlx-core 0.5.13", - "sqlx-rt 0.5.13", - "syn 1.0.109", - "url", -] - -[[package]] -name = "sqlx-macros" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9" -dependencies = [ - "dotenvy", - "either", - "heck", - "once_cell", - "proc-macro2", - "quote", - "sha2 0.10.7", - "sqlx-core 0.6.3", - "sqlx-rt 0.6.3", - "syn 1.0.109", - "url", -] - -[[package]] -name = "sqlx-rt" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4db708cd3e459078f85f39f96a00960bd841f66ee2a669e90bf36907f5a79aae" -dependencies = [ - "once_cell", - "tokio", - "tokio-rustls 0.22.0", -] - -[[package]] -name = "sqlx-rt" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024" -dependencies = [ - "once_cell", - "tokio", - "tokio-rustls 0.23.4", -] - -[[package]] -name = "stringprep" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3737bde7edce97102e0e2b15365bf7a20bfdb5f60f4f9e8d7004258a51a8da" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "subtle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" - -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "subtle-encoding" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" -dependencies = [ - "zeroize", -] - -[[package]] -name = "subtle-ng" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" -dependencies = [ - "cfg-if 1.0.0", - "fastrand", - "redox_syscall 0.3.5", - "rustix", - "windows-sys", -] - -[[package]] -name = "tendermint" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f0a7d05cf78524782337f8edd55cbc578d159a16ad4affe2135c92f7dbac7f0" -dependencies = [ - "bytes", - "digest 0.10.7", - "ed25519 2.2.2", - "ed25519-consensus", - "flex-error", - "futures", - "k256 0.13.1", - "num-traits", - "once_cell", - "prost", - "prost-types", - "ripemd", - "serde", - "serde_bytes", - "serde_json", - "serde_repr", - "sha2 0.10.7", - "signature 2.1.0", - "subtle 2.4.1", - "subtle-encoding", - "tendermint-proto", - "time", - "zeroize", -] - -[[package]] -name = "tendermint-config" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71a72dbbea6dde12045d261f2c70c0de039125675e8a026c8d5ad34522756372" -dependencies = [ - "flex-error", - "serde", - "serde_json", - "tendermint", - "toml 0.5.11", - "url", -] - -[[package]] -name = "tendermint-proto" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cec054567d16d85e8c3f6a3139963d1a66d9d3051ed545d31562550e9bcc3d" -dependencies = [ - "bytes", - "flex-error", - "num-derive", - "num-traits", - "prost", - "prost-types", - "serde", - "serde_bytes", - "subtle-encoding", - "time", -] - -[[package]] -name = "tendermint-rpc" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d119d83a130537fc4a98c3c9eb6899ebe857fea4860400a61675bfb5f0b35129" -dependencies = [ - "async-trait", - "bytes", - "flex-error", - "futures", - "getrandom 0.2.10", - "http", - "hyper", - "hyper-proxy", - "hyper-rustls", - "peg", - "pin-project", - "semver 1.0.18", - "serde", - "serde_bytes", - "serde_json", - "subtle 2.4.1", - "subtle-encoding", - "tendermint", - "tendermint-config", - "tendermint-proto", - "thiserror", - "time", - "tokio", - "tracing", - "url", - "uuid 0.8.2", - "walkdir", -] - -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thiserror" -version = "1.0.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "time" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea" -dependencies = [ - "deranged", - "itoa", - "js-sys", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" - -[[package]] -name = "time-macros" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" -dependencies = [ - "time-core", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "pin-project-lite", - "signal-hook-registry", - "socket2 0.5.3", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" -dependencies = [ - "rustls 0.19.1", - "tokio", - "webpki 0.21.4", -] - -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.8", - "tokio", - "webpki 0.22.0", -] - -[[package]] -name = "tokio-stream" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", - "tokio-util", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e96bb520beab540ab664bd5a9cfeaa1fcd846fa68c830b42e2c8963071251d2" -dependencies = [ - "futures-util", - "log", - "pin-project", - "tokio", - "tungstenite", -] - -[[package]] -name = "tokio-util" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "slab", - "tokio", - "tracing", -] - -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "toml" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.19.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" -dependencies = [ - "indexmap 2.0.0", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if 1.0.0", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "tungstenite" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe8dada8c1a3aeca77d6b51a4f1314e0f4b8e438b7b1b71e3ddaca8080e4093" -dependencies = [ - "base64 0.13.1", - "byteorder", - "bytes", - "http", - "httparse", - "input_buffer", - "log", - "rand 0.8.5", - "sha-1", - "thiserror", - "url", - "utf-8", -] - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - -[[package]] -name = "unicode-ident" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common", - "subtle 2.4.1", -] - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "url" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "uuid" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" - -[[package]] -name = "uuid" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" -dependencies = [ - "getrandom 0.2.10", - "wasm-bindgen", -] - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "vergen" -version = "7.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447f9238a4553957277b3ee09d80babeae0811f1b3baefb093de1c0448437a37" -dependencies = [ - "anyhow", - "cfg-if 1.0.0", - "enum-iterator", - "getset", - "git2", - "rustc_version", - "rustversion", - "thiserror", - "time", -] - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "walkdir" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" -dependencies = [ - "same-file", - "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.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[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.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" -dependencies = [ - "cfg-if 1.0.0", - "serde", - "serde_json", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 1.0.109", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" - -[[package]] -name = "wasm-bindgen-test" -version = "0.3.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d2fff962180c3fadf677438054b1db62bee4aa32af26a45388af07d1287e1d" -dependencies = [ - "console_error_panic_hook", - "js-sys", - "scoped-tls", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-bindgen-test-macro", -] - -[[package]] -name = "wasm-bindgen-test-macro" -version = "0.3.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4683da3dfc016f704c9f82cf401520c4f1cb3ee440f7f52b3d6ac29506a49ca7" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "wasm-utils" -version = "0.1.0" -dependencies = [ - "futures", - "getrandom 0.2.10", - "indexed_db_futures", - "js-sys", - "nym-store-cipher", - "serde", - "serde-wasm-bindgen", - "thiserror", - "tungstenite", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "wasmtimer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f656cd8858a5164932d8a90f936700860976ec21eb00e0fe2aa8cab13f6b4cf" -dependencies = [ - "futures", - "js-sys", - "parking_lot 0.12.1", - "pin-utils", - "slab", - "wasm-bindgen", -] - -[[package]] -name = "web-sys" -version = "0.3.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" -dependencies = [ - "webpki 0.21.4", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki 0.22.0", -] - -[[package]] -name = "wee_alloc" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "memory_units", - "winapi", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - -[[package]] -name = "winnow" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5504cc7644f4b593cbc05c4a55bf9bd4e94b867c3c0bd440934174d50482427d" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "x25519-dalek" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" -dependencies = [ - "curve25519-dalek", - "rand_core 0.5.1", - "serde", - "zeroize", -] - -[[package]] -name = "zeroize" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] diff --git a/clients/webassembly/Cargo.toml b/clients/webassembly/Cargo.toml deleted file mode 100644 index d68b5d37f6..0000000000 --- a/clients/webassembly/Cargo.toml +++ /dev/null @@ -1,74 +0,0 @@ -[package] -name = "nym-client-wasm" -authors = ["Dave Hrycyszyn ", "Jedrzej Stuczynski "] -version = "1.1.1" -edition = "2021" -keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"] -license = "Apache-2.0" -repository = "https://github.com/nymtech/nym" -description = "A webassembly client which can be used to interact with the the Nym privacy platform. Wasm is used for Sphinx packet generation." -rust-version = "1.56" - -[lib] -crate-type = ["cdylib", "rlib"] - -[features] -default = ["console_error_panic_hook"] -offline-test = [] - -[dependencies] -async-trait = "0.1.68" -bs58 = "0.4.0" -futures = "0.3" -js-sys = "0.3" -rand = { version = "0.7.3", features = ["wasm-bindgen"] } -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -anyhow = "1.0" -serde-wasm-bindgen = "0.5" -tokio = { version = "1.24.1", features = ["sync"] } -url = "2.2" -wasm-bindgen = { version = "=0.2.83", features = ["serde-serialize"] } -wasm-bindgen-futures = "0.4" -thiserror = "1.0.40" -zeroize = "1.6.0" - -wasmtimer = { version = "0.2.0", features = ["tokio"] } - -# internal -nym-node-tester-utils = { path = "../../common/node-tester-utils" } -nym-client-core = { path = "../../common/client-core", default-features = false, features = ["wasm"] } -nym-bandwidth-controller = { path = "../../common/bandwidth-controller" } -nym-coconut-interface = { path = "../../common/coconut-interface" } -nym-credentials = { path = "../../common/credentials" } -nym-credential-storage = { path = "../../common/credential-storage" } -nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "serde"] } -nym-sphinx = { path = "../../common/nymsphinx" } -nym-sphinx-acknowledgements = { path = "../../common/nymsphinx/acknowledgements", features = ["serde"]} -nym-topology = { path = "../../common/topology" } -nym-gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm"] } -nym-validator-client = { path = "../../common/client-libs/validator-client", default-features = false } -nym-task = { path = "../../common/task" } -wasm-utils = { path = "../../common/wasm-utils", features = ["storage"], default-features = false } -# The `console_error_panic_hook` crate provides better debugging of panics by -# logging them with `console.error`. This is great for development, but requires -# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for -# code size when deploying. -console_error_panic_hook = { version = "0.1", optional = true } - -# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size -# compared to the default allocator's ~10K. It is slower than the default -# allocator, however. -# -# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. -wee_alloc = { version = "0.4", optional = true } - -[dev-dependencies] -wasm-bindgen-test = "0.3" - -[package.metadata.wasm-pack.profile.release] -wasm-opt = false - -[profile.release] -lto = true -opt-level = 'z' diff --git a/clients/webassembly/LICENSE_APACHE b/clients/webassembly/LICENSE_APACHE deleted file mode 100644 index 1b5ec8b78e..0000000000 --- a/clients/webassembly/LICENSE_APACHE +++ /dev/null @@ -1,176 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS diff --git a/clients/webassembly/Makefile b/clients/webassembly/Makefile deleted file mode 100644 index 23d5b7eea6..0000000000 --- a/clients/webassembly/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -clippy: - cargo clippy --all-features --target wasm32-unknown-unknown -- -D warnings - -test: - wasm-pack test --node - -wasm-build: - wasm-pack build \ No newline at end of file diff --git a/clients/webassembly/internal-dev/worker.js b/clients/webassembly/internal-dev/worker.js deleted file mode 100644 index fe15532596..0000000000 --- a/clients/webassembly/internal-dev/worker.js +++ /dev/null @@ -1,382 +0,0 @@ -// Copyright 2020-2023 Nym Technologies SA -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -importScripts("nym_client_wasm.js"); - -console.log("Initializing worker"); - -// wasm_bindgen creates a global variable (with the exports attached) that is in scope after `importScripts` -const { - NymNodeTester, - WasmGateway, - WasmMixNode, - WasmNymTopology, - default_debug, - NymClientBuilder, - NymClient, - set_panic_hook, - Config, - GatewayEndpointConfig, - ClientStorage, - current_network_topology, - make_key, - make_key2, -} = wasm_bindgen; - -let client = null; -let tester = null; - -const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9"; - -function dummyTopology() { - const l1Mixnode = new WasmMixNode( - 1, - "n1fzv4jc7fanl9s0qj02ge2ezk3kts545kjtek47", - "178.79.143.65", - 1789, - "4Yr4qmEHd9sgsuQ83191FR2hD88RfsbMmB4tzhhZWriz", - "8ndjk5oZ6HxUZNScLJJ7hk39XtUqGexdKgW7hSX6kpWG", - 1, - "1.10.0" - ); - const l2Mixnode = new WasmMixNode( - 2, - "n1z93z44vf8ssvdhujjvxcj4rd5e3lz0l60wdk70", - "109.74.197.180", - 1789, - "7sVjiMrPYZrDWRujku9QLxgE8noT7NTgBAqizCsu7AoK", - "GepXwRnKZDd8x2nBWAajGGBVvF3mrpVMQBkgfrGuqRCN", - 2, - "1.10.0" - ); - const l3Mixnode = new WasmMixNode( - 3, - "n1ptg680vnmef2cd8l0s9uyc4f0hgf3x8sed6w77", - "176.58.101.80", - 1789, - "FoM5Mx9Pxk1g3zEqkS3APgtBeTtTo3M8k7Yu4bV6kK1R", - "DeYjrDC2AcQRVFshiKnbUo6bRvPyZ33QGYR2DLeFJ9qD", - 3, - "1.10.0" - ); - - const gateway = new WasmGateway( - "n16evnn8glr0sham3matj8rg2s24m6x56ayk87ts", - "85.159.212.96", - 1789, - 9000, - "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9", - "BtYjoWihiuFihGKQypmpSspbhmWDPxzqeTVSd8ciCpWL", - "1.10.1" - ); - - const mixnodes = new Map(); - mixnodes.set(1, [l1Mixnode]); - mixnodes.set(2, [l2Mixnode]); - mixnodes.set(3, [l3Mixnode]); - - const gateways = [gateway]; - - return new WasmNymTopology(mixnodes, gateways); -} - -function printAndDisplayTestResult(result) { - result.log_details(); - - self.postMessage({ - kind: "DisplayTesterResults", - args: { - score: result.score(), - sentPackets: result.sent_packets, - receivedPackets: result.received_packets, - receivedAcks: result.received_acks, - duplicatePackets: result.duplicate_packets, - duplicateAcks: result.duplicate_acks, - }, - }); -} - -async function testWithTester() { - // A) construct with hardcoded topology - const topology = dummyTopology(); - const nodeTester = await new NymNodeTester(topology, preferredGateway); - - // B) first get topology directly from nym-api - // const validator = 'https://qwerty-validator-api.qa.nymte.ch/api'; - // const topology = await current_network_topology(validator) - // const nodeTester = await new NymNodeTester(topology, preferredGateway); - // - // C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers) - // const validator = 'https://qwerty-validator-api.qa.nymte.ch/api'; - // const nodeTester = await NymNodeTester.new_with_api(validator, preferredGateway) - - // B) first get topology directly from nym-api - // const validator = 'https://qwerty-validator-api.qa.nymte.ch/api'; - // const topology = await current_network_topology(validator) - // const nodeTester = await new NymNodeTester(topology, undefined, preferredGateway); - // - // C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers) - // const validator = 'https://qwerty-validator-api.qa.nymte.ch/api'; - // const nodeTester = await NymNodeTester.new_with_api(validator, undefined, preferredGateway) - // D, E, F) you also don't have to specify the gateway. if you don't, a random one (from your topology) will be used - // const topology = dummyTopology() - // const nodeTester = await new NymNodeTester(topology); - - self.onmessage = async (event) => { - if (event.data && event.data.kind) { - switch (event.data.kind) { - case "TestPacket": { - const { mixnodeIdentity } = event.data.args; - console.log("starting node test..."); - - let result = await nodeTester.test_node(mixnodeIdentity); - printAndDisplayTestResult(result); - } - } - } - }; -} - -async function testerReconnection() { - const validator = "https://qwerty-validator-api.qa.nymte.ch/api"; - const nodeTester = await NymNodeTester.new_with_api(validator); - - self.onmessage = async (event) => { - if (event.data && event.data.kind) { - switch (event.data.kind) { - case "TestPacket": { - const { mixnodeIdentity } = event.data.args; - console.log("starting node test..."); - - let result1 = await nodeTester.test_node(mixnodeIdentity); - console.log("sleeping for 5s"); - await new Promise((r) => setTimeout(r, 5000)); - await nodeTester.disconnect_from_gateway(); - - console.log("sleeping for 5s"); - await new Promise((r) => setTimeout(r, 5000)); - - await nodeTester.reconnect_to_gateway(); - let result2 = await nodeTester.test_node(mixnodeIdentity); - - printAndDisplayTestResult(result1); - printAndDisplayTestResult(result2); - } - } - } - }; -} - -async function testWithNymClient() { - const topology = dummyTopology(); - - let received = 0; - - const onMessageHandler = (message) => { - received += 1; - self.postMessage({ - kind: "ReceiveMessage", - args: { - message, - senderTag: undefined, - isTestPacket: true, - }, - }); - - // it's really up to the user to create proper callback here... - console.log(`received ${received} packets so far`); - }; - - console.log("Instantiating WASM client..."); - - let clientBuilder = NymClientBuilder.new_tester( - topology, - onMessageHandler, - preferredGateway - ); - - console.log("Web worker creating WASM client..."); - let local_client = await clientBuilder.start_client(); - console.log("WASM client running!"); - - const selfAddress = local_client.self_address(); - - // set the global (I guess we don't have to anymore?) - client = local_client; - - console.log(`Client address is ${selfAddress}`); - self.postMessage({ - kind: "Ready", - args: { - selfAddress, - }, - }); - - // Set callback to handle messages passed to the worker. - self.onmessage = async (event) => { - console.log(event); - if (event.data && event.data.kind) { - switch (event.data.kind) { - case "SendMessage": { - const { message, recipient } = event.data.args; - let uint8Array = new TextEncoder().encode(message); - await client.send_regular_message(uint8Array, recipient); - break; - } - case "TestPacket": { - const { mixnodeIdentity } = event.data.args; - const req = await client.try_construct_test_packet_request( - mixnodeIdentity - ); - await client.change_hardcoded_topology(req.injectable_topology()); - await client.try_send_test_packets(req); - break; - } - } - } - }; -} - -async function normalNymClientUsage() { - self.postMessage({ kind: "DisableMagicTestButton" }); - - // only really useful if you want to adjust some settings like traffic rate - // (if not needed you can just pass a null) - const debug = default_debug(); - - debug.disable_main_poisson_packet_distribution = true; - debug.disable_loop_cover_traffic_stream = true; - debug.use_extended_packet_size = false; - // debug.average_packet_delay_ms = BigInt(10); - // debug.average_ack_delay_ms = BigInt(10); - // debug.ack_wait_addition_ms = BigInt(3000); - // debug.ack_wait_multiplier = 10; - - debug.topology_refresh_rate_ms = BigInt(60000); - - const preferredGateway = "336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9"; - const validator = "https://qwerty-validator-api.qa.nymte.ch/api"; - - const config = new Config("my-awesome-wasm-client", validator, debug); - - const onMessageHandler = (message) => { - console.log(message); - self.postMessage({ - kind: "ReceiveMessage", - args: { - message, - }, - }); - }; - - console.log("Instantiating WASM client..."); - - let localClient = await new NymClient(config, onMessageHandler); - console.log("WASM client running!"); - - const selfAddress = localClient.self_address(); - - // set the global (I guess we don't have to anymore?) - client = localClient; - - console.log(`Client address is ${selfAddress}`); - self.postMessage({ - kind: "Ready", - args: { - selfAddress, - }, - }); - - // Set callback to handle messages passed to the worker. - self.onmessage = async (event) => { - console.log(event); - if (event.data && event.data.kind) { - switch (event.data.kind) { - case "SendMessage": { - const { message, recipient } = event.data.args; - let uint8Array = new TextEncoder().encode(message); - await client.send_regular_message(uint8Array, recipient); - break; - } - } - } - }; -} - -async function messWithStorage() { - self.onmessage = async (event) => { - if (event.data && event.data.kind) { - switch (event.data.kind) { - case "TestPacket": { - const { mixnodeIdentity } = event.data.args; - console.log("button clicked...", mixnodeIdentity); - - let id1 = "one"; - let id2 = "two"; - - console.log("making store1 NO-ENC"); - let _storage1 = await ClientStorage.new_unencrypted(id1); - - console.log("making store2 ENC"); - let _storage2 = await new ClientStorage(id2, "my-secret-password"); - // - // - // - // console.log("attempting to use store1 WITH PASSWORD") - // let _storage1_alt = await new ClientStorage(id1, "password"); - // - // - // - // console.log("attempting to use store2 WITHOUT PASSWORD") - // let _storage2_alt = await ClientStorage.new_unencrypted(id2); - // - // - // - // console.log("attempting to use store2 with WRONG PASSWORD") - // let _storage2_bad = await new ClientStorage(id2, "bad-password") - - // - // console.log("read1: ", await storage1.read()); - // console.log("read2: ", await storage2.read()); - // - // console.log("store1: ", await storage1.store("FOOMP")); - // - // console.log("read1: ", await storage1.read()); - // console.log("read2: ", await storage2.read()); - } - } - } - }; -} - -async function main() { - // load WASM package - await wasm_bindgen("nym_client_wasm_bg.wasm"); - console.log("Loaded WASM"); - - // sets up better stack traces in case of in-rust panics - set_panic_hook(); - - // show reconnection capabilities - // await testerReconnection() - - // run test on simplified and dedicated tester: - await testWithTester(); - - // 'Normal' client setup (to send 'normal' messages) - // await normalNymClientUsage() -} - -// Let's get started! -main(); diff --git a/clients/webassembly/src/constants.rs b/clients/webassembly/src/constants.rs deleted file mode 100644 index db2481de34..0000000000 --- a/clients/webassembly/src/constants.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2023 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -pub(crate) const NODE_TESTER_ID: &str = "_nym-node-tester"; -pub(crate) const NODE_TESTER_CLIENT_ID: &str = "_nym-node-tester-client"; diff --git a/clients/webassembly/src/gateway_selector.rs b/clients/webassembly/src/gateway_selector.rs deleted file mode 100644 index 65cf0775ae..0000000000 --- a/clients/webassembly/src/gateway_selector.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2022 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use nym_client_core::config::GatewayEndpointConfig; -use wasm_bindgen::prelude::*; - -#[wasm_bindgen] -pub async fn get_gateway(api_server: String, preferred: Option) -> GatewayEndpointConfig { - let validator_client = - nym_validator_client::client::NymApiClient::new(api_server.parse().unwrap()); - - let gateways = match validator_client.get_cached_gateways().await { - Err(err) => panic!("failed to obtain list of all gateways - {err}"), - Ok(gateways) => gateways, - }; - - if let Some(preferred) = preferred { - if let Some(details) = gateways - .iter() - .find(|g| g.gateway.identity_key == preferred) - { - return GatewayEndpointConfig { - gateway_id: details.gateway.identity_key.clone(), - gateway_owner: details.owner.to_string(), - gateway_listener: format!( - "ws://{}:{}", - details.gateway.host, details.gateway.clients_port - ), - }; - } - } - - let details = gateways - .first() - .expect("current topology holds no gateways"); - - GatewayEndpointConfig { - gateway_id: details.gateway.identity_key.clone(), - gateway_owner: details.owner.to_string(), - gateway_listener: format!( - "ws://{}:{}", - details.gateway.host, details.gateway.clients_port - ), - } -} diff --git a/clients/webassembly/src/lib.rs b/clients/webassembly/src/lib.rs deleted file mode 100644 index a4d3aeaad4..0000000000 --- a/clients/webassembly/src/lib.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2021-2023 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -// After reading https://github.com/rust-lang/rust-clippy/issues/11382 -// I suspect we *maybe* have hit a false positive, but I'm not sure. -#![allow(clippy::arc_with_non_send_sync)] - -use wasm_bindgen::prelude::*; - -#[cfg(target_arch = "wasm32")] -mod client; -#[cfg(target_arch = "wasm32")] -pub mod encoded_payload_helper; -#[cfg(target_arch = "wasm32")] -pub mod error; -#[cfg(target_arch = "wasm32")] -pub mod gateway_selector; -#[cfg(target_arch = "wasm32")] -pub mod storage; -#[cfg(target_arch = "wasm32")] -pub mod tester; -#[cfg(target_arch = "wasm32")] -pub mod topology; -#[cfg(target_arch = "wasm32")] -pub mod validation; - -#[cfg(target_arch = "wasm32")] -mod helpers; - -mod constants; - -#[wasm_bindgen] -pub fn set_panic_hook() { - // When the `console_error_panic_hook` feature is enabled, we can call the - // `set_panic_hook` function at least once during initialization, and then - // we will get better error messages if our code ever panics. - // - // For more details see - // https://github.com/rustwasm/console_error_panic_hook#readme - #[cfg(feature = "console_error_panic_hook")] - console_error_panic_hook::set_once(); -} diff --git a/clients/webassembly/src/storage/error.rs b/clients/webassembly/src/storage/error.rs deleted file mode 100644 index fcb6db5ad1..0000000000 --- a/clients/webassembly/src/storage/error.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2023 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use thiserror::Error; -use wasm_bindgen::JsValue; -use wasm_utils::simple_js_error; -use wasm_utils::storage::error::StorageError; - -#[derive(Debug, Error)] -pub enum ClientStorageError { - #[error("failed to use the storage: {source}")] - StorageError { - #[from] - source: StorageError, - }, - - #[error("{typ} cryptographic key is not available in storage")] - CryptoKeyNotInStorage { typ: String }, - - #[error("the prior gateway details are not available in the storage")] - GatewayDetailsNotInStorage, -} - -impl From for JsValue { - fn from(value: ClientStorageError) -> Self { - simple_js_error(value.to_string()) - } -} diff --git a/clients/webassembly/src/storage/mod.rs b/clients/webassembly/src/storage/mod.rs deleted file mode 100644 index f4ab912657..0000000000 --- a/clients/webassembly/src/storage/mod.rs +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright 2023 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use crate::client::config::Config; -use crate::storage::error::ClientStorageError; -use js_sys::Promise; -use nym_client_core::client::base_client::storage::gateway_details::PersistedGatewayDetails; -use nym_crypto::asymmetric::{encryption, identity}; -use nym_gateway_client::SharedKeys; -use nym_sphinx::acknowledgements::AckKey; -use std::sync::Arc; -use wasm_bindgen::prelude::*; -use wasm_bindgen_futures::future_to_promise; -use wasm_utils::storage::{IdbVersionChangeEvent, WasmStorage}; -use wasm_utils::PromisableResult; -use zeroize::Zeroizing; - -pub(crate) mod error; -pub(crate) mod traits; - -const STORAGE_NAME_PREFIX: &str = "wasm-client-storage"; -const STORAGE_VERSION: u32 = 1; - -// v1 tables -mod v1 { - // stores - pub const KEYS_STORE: &str = "keys"; - pub const CORE_STORE: &str = "core"; - - // keys - pub const CONFIG: &str = "config"; - pub const GATEWAY_DETAILS: &str = "gateway_details"; - - pub const ED25519_IDENTITY_KEYPAIR: &str = "ed25519_identity_keypair"; - pub const X25519_ENCRYPTION_KEYPAIR: &str = "x25519_encryption_keypair"; - - // TODO: for those we could actually use the subtle crypto storage - pub const AES128CTR_ACK_KEY: &str = "aes128ctr_ack_key"; - pub const AES128CTR_BLAKE3_HMAC_GATEWAY_KEYS: &str = "aes128ctr_blake3_hmac_gateway_keys"; -} - -#[wasm_bindgen] -pub struct ClientStorage { - #[allow(dead_code)] - pub(crate) name: String, - pub(crate) inner: Arc, -} - -#[wasm_bindgen] -impl ClientStorage { - fn db_name(client_id: &str) -> String { - format!("{STORAGE_NAME_PREFIX}-{client_id}") - } - - pub(crate) async fn new_async( - client_id: &str, - passphrase: Option, - ) -> Result { - let name = Self::db_name(client_id); - - // make sure the password is zeroized when no longer used, especially if we error out. - // special care must be taken on JS side to ensure it's correctly used there. - let passphrase = Zeroizing::new(passphrase); - - let migrate_fn = Some(|evt: &IdbVersionChangeEvent| -> Result<(), JsValue> { - // Even if the web-sys bindings expose the version as a f64, the IndexedDB API - // works with an unsigned integer. - // See - let old_version = evt.old_version() as u32; - - if old_version < 1 { - // migrating to version 1 - let db = evt.db(); - - db.create_object_store(v1::KEYS_STORE)?; - db.create_object_store(v1::CORE_STORE)?; - } - - Ok(()) - }); - - let inner = WasmStorage::new( - &name, - STORAGE_VERSION, - migrate_fn, - passphrase.as_ref().map(|p| p.as_bytes()), - ) - .await?; - - Ok(ClientStorage { - inner: Arc::new(inner), - name, - }) - } - - #[wasm_bindgen(constructor)] - #[allow(clippy::new_ret_no_self)] - pub fn new(client_id: String, passphrase: String) -> Promise { - future_to_promise(async move { - Self::new_async(&client_id, Some(passphrase)) - .await - .into_promise_result() - }) - } - - pub fn new_unencrypted(client_id: String) -> Promise { - future_to_promise(async move { - Self::new_async(&client_id, None) - .await - .into_promise_result() - }) - } - - // TODO: persist client's config - #[allow(dead_code)] - pub(crate) async fn read_config(&self) -> Result, ClientStorageError> { - self.inner - .read_value(v1::CORE_STORE, JsValue::from_str(v1::CONFIG)) - .await - .map_err(Into::into) - } - - pub(crate) async fn may_read_gateway_details( - &self, - ) -> Result, ClientStorageError> { - self.inner - .read_value(v1::CORE_STORE, JsValue::from_str(v1::GATEWAY_DETAILS)) - .await - .map_err(Into::into) - } - - pub(crate) async fn must_read_gateway_details( - &self, - ) -> Result { - self.may_read_gateway_details() - .await? - .ok_or(ClientStorageError::GatewayDetailsNotInStorage) - } - - async fn may_read_identity_keypair( - &self, - ) -> Result, ClientStorageError> { - self.inner - .read_value( - v1::KEYS_STORE, - JsValue::from_str(v1::ED25519_IDENTITY_KEYPAIR), - ) - .await - .map_err(Into::into) - } - - async fn may_read_encryption_keypair( - &self, - ) -> Result, ClientStorageError> { - self.inner - .read_value( - v1::KEYS_STORE, - JsValue::from_str(v1::X25519_ENCRYPTION_KEYPAIR), - ) - .await - .map_err(Into::into) - } - - async fn may_read_ack_key(&self) -> Result, ClientStorageError> { - self.inner - .read_value(v1::KEYS_STORE, JsValue::from_str(v1::AES128CTR_ACK_KEY)) - .await - .map_err(Into::into) - } - - async fn may_read_gateway_shared_key(&self) -> Result, ClientStorageError> { - self.inner - .read_value( - v1::KEYS_STORE, - JsValue::from_str(v1::AES128CTR_BLAKE3_HMAC_GATEWAY_KEYS), - ) - .await - .map_err(Into::into) - } - - async fn must_read_identity_keypair(&self) -> Result { - self.may_read_identity_keypair() - .await? - .ok_or(ClientStorageError::CryptoKeyNotInStorage { - typ: v1::ED25519_IDENTITY_KEYPAIR.to_string(), - }) - } - - async fn must_read_encryption_keypair( - &self, - ) -> Result { - self.may_read_encryption_keypair() - .await? - .ok_or(ClientStorageError::CryptoKeyNotInStorage { - typ: v1::X25519_ENCRYPTION_KEYPAIR.to_string(), - }) - } - - async fn must_read_ack_key(&self) -> Result { - self.may_read_ack_key() - .await? - .ok_or(ClientStorageError::CryptoKeyNotInStorage { - typ: v1::AES128CTR_ACK_KEY.to_string(), - }) - } - - async fn must_read_gateway_shared_key(&self) -> Result { - self.may_read_gateway_shared_key() - .await? - .ok_or(ClientStorageError::CryptoKeyNotInStorage { - typ: v1::AES128CTR_BLAKE3_HMAC_GATEWAY_KEYS.to_string(), - }) - } - - async fn store_identity_keypair( - &self, - keypair: &identity::KeyPair, - ) -> Result<(), ClientStorageError> { - self.inner - .store_value( - v1::KEYS_STORE, - JsValue::from_str(v1::ED25519_IDENTITY_KEYPAIR), - keypair, - ) - .await - .map_err(Into::into) - } - - async fn store_encryption_keypair( - &self, - keypair: &encryption::KeyPair, - ) -> Result<(), ClientStorageError> { - self.inner - .store_value( - v1::KEYS_STORE, - JsValue::from_str(v1::X25519_ENCRYPTION_KEYPAIR), - keypair, - ) - .await - .map_err(Into::into) - } - - async fn store_ack_key(&self, key: &AckKey) -> Result<(), ClientStorageError> { - self.inner - .store_value( - v1::KEYS_STORE, - JsValue::from_str(v1::AES128CTR_ACK_KEY), - key, - ) - .await - .map_err(Into::into) - } - - async fn store_gateway_shared_key(&self, key: &SharedKeys) -> Result<(), ClientStorageError> { - self.inner - .store_value( - v1::KEYS_STORE, - JsValue::from_str(v1::AES128CTR_BLAKE3_HMAC_GATEWAY_KEYS), - key, - ) - .await - .map_err(Into::into) - } - - pub(crate) async fn store_gateway_details( - &self, - gateway_endpoint: &PersistedGatewayDetails, - ) -> Result<(), ClientStorageError> { - self.inner - .store_value( - v1::CORE_STORE, - JsValue::from_str(v1::GATEWAY_DETAILS), - gateway_endpoint, - ) - .await - .map_err(Into::into) - } - - // TODO: persist client's config - #[allow(dead_code)] - pub(crate) async fn store_config(&self, config: &Config) -> Result<(), ClientStorageError> { - self.inner - .store_value(v1::CORE_STORE, JsValue::from_str(v1::CONFIG), config) - .await - .map_err(Into::into) - } - - pub(crate) async fn has_full_gateway_info(&self) -> Result { - let has_keys = self.may_read_gateway_shared_key().await?.is_some(); - let has_details = self.may_read_gateway_details().await?.is_some(); - - Ok(has_keys && has_details) - } -} diff --git a/clients/webassembly/src/topology.rs b/clients/webassembly/src/topology.rs deleted file mode 100644 index a706c3293b..0000000000 --- a/clients/webassembly/src/topology.rs +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright 2023 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use nym_client_core::config::GatewayEndpointConfig; -use nym_crypto::asymmetric::{encryption, identity}; -use nym_topology::gateway::GatewayConversionError; -use nym_topology::mix::{Layer, MixnodeConversionError}; -use nym_topology::{gateway, mix, MixLayer, NymTopology}; -use nym_validator_client::client::{IdentityKeyRef, MixId}; -use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; -use thiserror::Error; -use wasm_bindgen::prelude::wasm_bindgen; -use wasm_bindgen::JsValue; -use wasm_utils::{console_log, simple_js_error}; - -#[derive(Debug, Error)] -pub enum WasmTopologyError { - #[error("got invalid mix layer {value}. Expected 1, 2 or 3.")] - InvalidMixLayer { value: u8 }, - - #[error(transparent)] - GatewayConversion(#[from] GatewayConversionError), - - #[error(transparent)] - MixnodeConversion(#[from] MixnodeConversionError), - - #[error("The provided mixnode map was malformed: {source}")] - MalformedMixnodeMap { source: serde_wasm_bindgen::Error }, - - #[error("The provided gateway list was malformed: {source}")] - MalformedGatewayList { source: serde_wasm_bindgen::Error }, -} - -impl From for JsValue { - fn from(value: WasmTopologyError) -> Self { - simple_js_error(value.to_string()) - } -} - -#[wasm_bindgen] -#[derive(Debug)] -pub struct WasmNymTopology { - inner: NymTopology, -} - -#[wasm_bindgen] -impl WasmNymTopology { - #[wasm_bindgen(constructor)] - pub fn new( - // expected: BTreeMap>, - // HashMap> will also work because it has the same json representation - mixnodes: JsValue, - // expected: Vec - gateways: JsValue, - ) -> Result { - let mixnodes: BTreeMap> = - serde_wasm_bindgen::from_value(mixnodes) - .map_err(|source| WasmTopologyError::MalformedMixnodeMap { source })?; - - let gateways: Vec = serde_wasm_bindgen::from_value(gateways) - .map_err(|source| WasmTopologyError::MalformedGatewayList { source })?; - - let mut converted_mixes = BTreeMap::new(); - - for (layer, nodes) in mixnodes { - let layer_nodes = nodes - .into_iter() - .map(TryInto::try_into) - .collect::>()?; - - converted_mixes.insert(layer, layer_nodes); - } - - let gateways = gateways - .into_iter() - .map(TryInto::try_into) - .collect::>()?; - - Ok(WasmNymTopology { - inner: NymTopology::new(converted_mixes, gateways), - }) - } - - #[allow(dead_code)] - pub(crate) fn ensure_contains(&self, gateway_config: &GatewayEndpointConfig) -> bool { - self.ensure_contains_gateway_id(&gateway_config.gateway_id) - } - - pub(crate) fn ensure_contains_gateway_id(&self, gateway_id: IdentityKeyRef) -> bool { - self.inner - .gateways() - .iter() - .any(|g| g.identity_key.to_base58_string() == gateway_id) - } - - pub fn print(&self) { - if !self.inner.mixes().is_empty() { - console_log!("mixnodes:"); - for (layer, nodes) in self.inner.mixes() { - console_log!("\tlayer {layer}:"); - for node in nodes { - console_log!("\t\t{} - {}", node.mix_id, node.identity_key) - } - } - } else { - console_log!("NO MIXNODES") - } - - if !self.inner.gateways().is_empty() { - console_log!("gateways:"); - for gateway in self.inner.gateways() { - console_log!("\t{}", gateway.identity_key) - } - } else { - console_log!("NO GATEWAYS") - } - } -} - -impl From for NymTopology { - fn from(value: WasmNymTopology) -> Self { - value.inner - } -} - -impl From for WasmNymTopology { - fn from(value: NymTopology) -> Self { - WasmNymTopology { inner: value } - } -} - -#[wasm_bindgen] -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct WasmMixNode { - pub mix_id: MixId, - #[wasm_bindgen(getter_with_clone)] - pub owner: String, - #[wasm_bindgen(getter_with_clone)] - pub host: String, - pub mix_port: u16, - #[wasm_bindgen(getter_with_clone)] - pub identity_key: String, - #[wasm_bindgen(getter_with_clone)] - pub sphinx_key: String, - pub layer: MixLayer, - #[wasm_bindgen(getter_with_clone)] - pub version: String, -} - -#[wasm_bindgen] -impl WasmMixNode { - #[wasm_bindgen(constructor)] - #[allow(clippy::too_many_arguments)] - pub fn new( - mix_id: MixId, - owner: String, - host: String, - mix_port: u16, - identity_key: String, - sphinx_key: String, - layer: MixLayer, - version: String, - ) -> Self { - Self { - mix_id, - owner, - host, - mix_port, - identity_key, - sphinx_key, - layer, - version, - } - } -} - -impl TryFrom for mix::Node { - type Error = WasmTopologyError; - - fn try_from(value: WasmMixNode) -> Result { - let host = mix::Node::parse_host(&value.host)?; - - // try to completely resolve the host in the mix situation to avoid doing it every - // single time we want to construct a path - let mix_host = mix::Node::extract_mix_host(&host, value.mix_port)?; - - Ok(mix::Node { - mix_id: value.mix_id, - owner: value.owner, - host, - mix_host, - identity_key: identity::PublicKey::from_base58_string(&value.identity_key) - .map_err(MixnodeConversionError::from)?, - sphinx_key: encryption::PublicKey::from_base58_string(&value.sphinx_key) - .map_err(MixnodeConversionError::from)?, - layer: Layer::try_from(value.layer) - .map_err(|_| WasmTopologyError::InvalidMixLayer { value: value.layer })?, - version: value.version, - }) - } -} - -#[wasm_bindgen] -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct WasmGateway { - #[wasm_bindgen(getter_with_clone)] - pub owner: String, - #[wasm_bindgen(getter_with_clone)] - pub host: String, - pub mix_port: u16, - pub clients_port: u16, - #[wasm_bindgen(getter_with_clone)] - pub identity_key: String, - #[wasm_bindgen(getter_with_clone)] - pub sphinx_key: String, - #[wasm_bindgen(getter_with_clone)] - pub version: String, -} - -#[wasm_bindgen] -impl WasmGateway { - #[wasm_bindgen(constructor)] - pub fn new( - owner: String, - host: String, - mix_port: u16, - clients_port: u16, - identity_key: String, - sphinx_key: String, - version: String, - ) -> Self { - Self { - owner, - host, - mix_port, - clients_port, - identity_key, - sphinx_key, - version, - } - } -} - -impl TryFrom for gateway::Node { - type Error = WasmTopologyError; - - fn try_from(value: WasmGateway) -> Result { - let host = gateway::Node::parse_host(&value.host)?; - - // try to completely resolve the host in the mix situation to avoid doing it every - // single time we want to construct a path - let mix_host = gateway::Node::extract_mix_host(&host, value.mix_port)?; - - Ok(gateway::Node { - owner: value.owner, - host, - mix_host, - clients_port: value.clients_port, - identity_key: identity::PublicKey::from_base58_string(&value.identity_key) - .map_err(GatewayConversionError::from)?, - sphinx_key: encryption::PublicKey::from_base58_string(&value.sphinx_key) - .map_err(GatewayConversionError::from)?, - version: value.version, - }) - } -} diff --git a/clients/webassembly/src/validation.rs b/clients/webassembly/src/validation.rs deleted file mode 100644 index 830a3d789a..0000000000 --- a/clients/webassembly/src/validation.rs +++ /dev/null @@ -1,35 +0,0 @@ -use nym_sphinx::addressing::clients::Recipient; -use wasm_bindgen::prelude::*; - -#[wasm_bindgen] -pub fn validate_recipient(recipient: String) -> Result<(), JsError> { - match Recipient::try_from_base58_string(recipient) { - Ok(_) => Ok(()), - Err(e) => Err(JsError::new(format!("{}", e).as_str())), - } -} - -#[cfg(test)] -mod tests { - use super::validate_recipient; - use wasm_bindgen_test::*; - - #[wasm_bindgen_test] - fn test_recipient_validation_ok() { - let res = validate_recipient("DyQmXnst5NGGjzUZxRC5Bjs5bd7CBF3xMpsSmbRiizr2.GH6YTBP2NXU3AVqd8WjiTMVyeMjunXMEsp7gVCMEJqpD@336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9".to_string()); - assert!(res.is_ok()) - } - - #[wasm_bindgen_test] - fn test_recipient_validation_fails() { - assert!(validate_recipient(" DyQmXnst5NGGjzUZxRC5Bjs5bd7CBF3xMpsSmbRiizr2.GH6YTBP2NXU3AVqd8WjiTMVyeMjunXMEsp7gVCMEJqpD@336yuXAeGEgedRfqTJZsG2YV7P13QH1bHv1SjCZYarc9".to_string()).is_err()); - assert!(validate_recipient( - "DyQmXnst5NGGjzUZxRC5BjbRiizr2.GH6YTBP2NXU3AVqd8WD@336yuXAeGEgedRfqTJZQH1bHv1SjCZYarc9" - .to_string() - ) - .is_err()); - assert!(validate_recipient("🙀🙀🙀🙀".to_string()).is_err()); - assert!(validate_recipient("".to_string()).is_err()); - assert!(validate_recipient(" ".to_string()).is_err()); - } -} diff --git a/clients/webassembly/tests/web.rs b/clients/webassembly/tests/web.rs deleted file mode 100644 index de5c1dafef..0000000000 --- a/clients/webassembly/tests/web.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! Test suite for the Web and headless browsers. - -#![cfg(target_arch = "wasm32")] - -extern crate wasm_bindgen_test; -use wasm_bindgen_test::*; - -wasm_bindgen_test_configure!(run_in_browser); - -#[wasm_bindgen_test] -fn pass() { - assert_eq!(1 + 1, 2); -} diff --git a/common/client-core/Cargo.toml b/common/client-core/Cargo.toml index 1c5c40a6e1..14761acf01 100644 --- a/common/client-core/Cargo.toml +++ b/common/client-core/Cargo.toml @@ -22,11 +22,11 @@ serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } sha2 = "0.10.6" tap = "1.0.1" -thiserror = "1.0.34" -time = "0.3.17" -tokio = { version = "1.24.1", features = ["macros"]} -tungstenite = { version = "0.13.0", default-features = false } +thiserror = { workspace = true } url = { workspace = true, features = ["serde"] } +tungstenite = { version = "0.13.0", default-features = false } +tokio = { workspace = true, features = ["macros"]} +time = "0.3.17" zeroize = { workspace = true } # internal @@ -51,7 +51,7 @@ version = "0.1.11" features = ["time"] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio] -version = "1.24.1" +workspace = true features = ["time"] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite] @@ -63,10 +63,10 @@ features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] optional = true [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen-futures] -version = "0.4" +workspace = true [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen] -version = "0.2.83" +workspace = true [target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer] workspace = true @@ -77,7 +77,7 @@ version = "0.2.4" features = ["futures"] [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-utils] -path = "../wasm-utils" +path = "../wasm/utils" features = ["websocket"] [target."cfg(target_arch = \"wasm32\")".dependencies.time] @@ -88,7 +88,7 @@ features = ["wasm-bindgen"] tempfile = "3.1.0" [build-dependencies] -tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] } +tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] } [features] diff --git a/common/client-core/src/client/replies/reply_storage/backend/mod.rs b/common/client-core/src/client/replies/reply_storage/backend/mod.rs index 72efa4b67f..557346a2da 100644 --- a/common/client-core/src/client/replies/reply_storage/backend/mod.rs +++ b/common/client-core/src/client/replies/reply_storage/backend/mod.rs @@ -6,7 +6,7 @@ use async_trait::async_trait; use std::error::Error; use thiserror::Error; -#[cfg(target_arch = "wasm32")] +// TODO: this should now live inside our wasm/client-core pub mod browser_backend; #[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))] diff --git a/common/client-core/src/config/disk_persistence/old_v1_1_20_2.rs b/common/client-core/src/config/disk_persistence/old_v1_1_20_2.rs index 3346dca6ca..d26cf1461c 100644 --- a/common/client-core/src/config/disk_persistence/old_v1_1_20_2.rs +++ b/common/client-core/src/config/disk_persistence/old_v1_1_20_2.rs @@ -3,6 +3,7 @@ use crate::config::disk_persistence::keys_paths::ClientKeysPaths; use crate::config::disk_persistence::{CommonClientPaths, DEFAULT_GATEWAY_DETAILS_FILENAME}; +use crate::error::ClientCoreError; use serde::{Deserialize, Serialize}; use std::path::PathBuf; @@ -15,16 +16,17 @@ pub struct CommonClientPathsV1_1_20_2 { } impl CommonClientPathsV1_1_20_2 { - pub fn upgrade_default(self) -> CommonClientPaths { - let data_dir = self - .reply_surb_database - .parent() - .expect("client paths upgrade failure"); - CommonClientPaths { + pub fn upgrade_default(self) -> Result { + let data_dir = self.reply_surb_database.parent().ok_or_else(|| { + ClientCoreError::UnableToUpgradeConfigFile { + new_version: "1.1.20-2".to_string(), + } + })?; + Ok(CommonClientPaths { keys: self.keys, gateway_details: data_dir.join(DEFAULT_GATEWAY_DETAILS_FILENAME), credentials_database: self.credentials_database, reply_surb_database: self.reply_surb_database, - } + }) } } diff --git a/common/client-core/src/config/mod.rs b/common/client-core/src/config/mod.rs index c1d5b9d3cb..e11f523276 100644 --- a/common/client-core/src/config/mod.rs +++ b/common/client-core/src/config/mod.rs @@ -69,7 +69,11 @@ pub struct Config { } impl Config { - pub fn new>(id: S, version: S) -> Self { + pub fn new(id: S1, version: S2) -> Self + where + S1: Into, + S2: Into, + { Config { client: Client::new_default(id, version), debug: Default::default(), @@ -287,7 +291,11 @@ pub struct Client { } impl Client { - pub fn new_default>(id: S, version: S) -> Self { + pub fn new_default(id: S1, version: S2) -> Self + where + S1: Into, + S2: Into, + { let network = NymNetworkDetails::new_mainnet(); let nyxd_urls = network .endpoints diff --git a/common/client-core/src/error.rs b/common/client-core/src/error.rs index c0dc76f1e6..0c30c149cb 100644 --- a/common/client-core/src/error.rs +++ b/common/client-core/src/error.rs @@ -119,6 +119,9 @@ pub enum ClientCoreError { #[error("the provided gateway details (for gateway {gateway_id}) do not correspond to the shared keys")] MismatchedGatewayDetails { gateway_id: String }, + + #[error("unable to upgrade config file to `{new_version}`")] + UnableToUpgradeConfigFile { new_version: String }, } /// Set of messages that the client can send to listeners via the task manager diff --git a/common/client-core/src/init/mod.rs b/common/client-core/src/init/mod.rs index 8e848837ef..1f8e10bcc9 100644 --- a/common/client-core/src/init/mod.rs +++ b/common/client-core/src/init/mod.rs @@ -106,14 +106,17 @@ pub enum GatewaySetup { /// Should the new gateway be selected based on latency. by_latency: bool, }, + Specified { /// Identity key of the gateway we want to try to use. gateway_identity: IdentityKey, }, + Predefined { /// Full gateway configuration details: PersistedGatewayDetails, }, + ReuseConnection { /// The authenticated ephemeral client that was created during `init` authenticated_ephemeral_client: GatewayClient, diff --git a/common/client-libs/gateway-client/Cargo.toml b/common/client-libs/gateway-client/Cargo.toml index 3f8f4ac0e4..f859b648d2 100644 --- a/common/client-libs/gateway-client/Cargo.toml +++ b/common/client-libs/gateway-client/Cargo.toml @@ -36,7 +36,7 @@ default-features = false # non-wasm-only dependencies [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio] -version = "1.24.1" +workspace = true features = ["macros", "rt", "net", "sync", "time"] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream] @@ -48,15 +48,18 @@ version = "0.14" # wasm-only dependencies [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen] -version = "0.2" +workspace = true [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen-futures] -version = "0.4" +workspace = true [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-utils] -path = "../../wasm-utils" +path = "../../wasm/utils" features = ["websocket"] +[target."cfg(target_arch = \"wasm32\")".dependencies.gloo-utils] +workspace = true + # only import it in wasm. Prefer proper tokio timer in non-wasm [target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer] workspace = true @@ -68,7 +71,7 @@ features = ["tokio"] # containing javascript (such as a web browser or node.js). # refer to https://docs.rs/getrandom/0.2.2/getrandom/#webassembly-support for more information [target."cfg(target_arch = \"wasm32\")".dependencies.getrandom] -version = "0.2" +workspace = true features = ["js"] [dev-dependencies] diff --git a/common/client-libs/gateway-client/src/client.rs b/common/client-libs/gateway-client/src/client.rs index 188d84e2c9..3cd75b1b5f 100644 --- a/common/client-libs/gateway-client/src/client.rs +++ b/common/client-libs/gateway-client/src/client.rs @@ -141,8 +141,8 @@ impl GatewayClient { #[cfg(target_arch = "wasm32")] async fn _close_connection(&mut self) -> Result<(), GatewayClientError> { match std::mem::replace(&mut self.connection, SocketState::NotConnected) { - SocketState::Available(mut socket) => { - (*socket).close(None).await; + SocketState::Available(socket) => { + (*socket).close(None, None).await?; Ok(()) } SocketState::PartiallyDelegated(_) => { @@ -175,7 +175,9 @@ impl GatewayClient { pub async fn establish_connection(&mut self) -> Result<(), GatewayClientError> { let ws_stream = match JSWebsocket::new(&self.gateway_address) { Ok(ws_stream) => ws_stream, - Err(e) => return Err(GatewayClientError::NetworkErrorWasm(e)), + Err(e) => { + return Err(GatewayClientError::NetworkErrorWasm(e)); + } }; self.connection = SocketState::Available(Box::new(ws_stream)); diff --git a/common/client-libs/gateway-client/src/error.rs b/common/client-libs/gateway-client/src/error.rs index 64414bcf99..8ac387b43f 100644 --- a/common/client-libs/gateway-client/src/error.rs +++ b/common/client-libs/gateway-client/src/error.rs @@ -1,12 +1,12 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +#[cfg(target_arch = "wasm32")] +use gloo_utils::errors::JsError; use nym_gateway_requests::registration::handshake::error::HandshakeError; use std::io; use thiserror::Error; use tungstenite::Error as WsError; -#[cfg(target_arch = "wasm32")] -use wasm_bindgen::JsValue; #[derive(Debug, Error)] pub enum GatewayClientError { @@ -19,10 +19,9 @@ pub enum GatewayClientError { #[error("There was a network error - {0}")] NetworkError(#[from] WsError), - // TODO: see if `JsValue` is a reasonable type for this #[cfg(target_arch = "wasm32")] #[error("There was a network error")] - NetworkErrorWasm(JsValue), + NetworkErrorWasm(#[from] JsError), #[error("Invalid URL - {0}")] InvalidURL(String), diff --git a/common/credential-storage/src/ephemeral_storage.rs b/common/credential-storage/src/ephemeral_storage.rs index 261f88cb63..577a2de8c5 100644 --- a/common/credential-storage/src/ephemeral_storage.rs +++ b/common/credential-storage/src/ephemeral_storage.rs @@ -5,9 +5,10 @@ use crate::backends::memory::CoconutCredentialManager; use crate::error::StorageError; use crate::models::CoconutCredential; use crate::storage::Storage; - use async_trait::async_trait; +pub type EphemeralCredentialStorage = EphemeralStorage; + // note that clone here is fine as upon cloning the same underlying pool will be used #[derive(Clone)] pub struct EphemeralStorage { diff --git a/common/http-requests/Cargo.toml b/common/http-requests/Cargo.toml new file mode 100644 index 0000000000..6245eeedf4 --- /dev/null +++ b/common/http-requests/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "nym-http-requests" +version = "0.1.0" +description = "Helper library for sending HTTP requesters over the Nym mixnet" +edition = { workspace = true } +authors = { workspace = true } +license = { workspace = true } +repository = { workspace = true } + +[dependencies] +nym-socks5-requests = { path = "../socks5/requests" } +nym-ordered-buffer = { path = "../socks5/ordered-buffer" } +nym-service-providers-common = { path = "../../service-providers/common" } +bytecodec = "0.4.15" +httpcodec = "0.2.3" +bytes = "1" +http = "0.2.9" +thiserror = "1" +url = "2" diff --git a/common/http-requests/src/error.rs b/common/http-requests/src/error.rs new file mode 100644 index 0000000000..180a4fd44a --- /dev/null +++ b/common/http-requests/src/error.rs @@ -0,0 +1,23 @@ +use std::io; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum MixHttpRequestError { + #[error("invalid Socks5 response")] + InvalidSocks5Response, + + #[error("the received Socks5 response was empty")] + EmptySocks5Response, + + #[error("bytecodec Error: {0}")] + ByteCodecError(#[from] bytecodec::Error), + + #[error("Url parse error: {0}")] + UrlParseError(#[from] url::ParseError), + + #[error("could not resolve socket address from the provided URL")] + SocketAddrResolveError { + #[source] + source: io::Error, + }, +} diff --git a/common/http-requests/src/lib.rs b/common/http-requests/src/lib.rs new file mode 100644 index 0000000000..1905396279 --- /dev/null +++ b/common/http-requests/src/lib.rs @@ -0,0 +1,63 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use bytecodec::bytes::BytesEncoder; +use bytecodec::io::IoEncodeExt; +use bytecodec::Encode; +use httpcodec::{BodyEncoder, Request, RequestEncoder}; + +pub mod error; +pub mod socks; + +pub fn encode_http_request_as_string( + request: Request>, +) -> Result { + // Encode HTTP request as bytes + let mut encoder = RequestEncoder::new(BodyEncoder::new(BytesEncoder::new())); + encoder.start_encoding(request)?; + let mut buf = Vec::new(); + encoder.encode_all(&mut buf)?; + + Ok(String::from_utf8_lossy(&buf).to_string()) +} + +#[cfg(test)] +mod http_requests_tests { + use super::*; + use httpcodec::{HeaderField, HttpVersion, Method, RequestTarget}; + + fn create_http_get_request() -> Request> { + let mut request = Request::new( + Method::new("GET").unwrap(), + RequestTarget::new("/.wellknown/wallet/validators.json").unwrap(), + HttpVersion::V1_1, + b"".to_vec(), + ); + let mut headers = request.header_mut(); + headers.add_field(HeaderField::new("Host", "nymtech.net").unwrap()); + + request + } + + #[test] + fn http_request_ok() { + // Encode HTTP request as bytes + let request = create_http_get_request(); + let mut encoder = RequestEncoder::new(BodyEncoder::new(BytesEncoder::new())); + encoder.start_encoding(request).unwrap(); + let mut buf = Vec::new(); + encoder.encode_all(&mut buf).unwrap(); + + let body_as_string = String::from_utf8(buf).unwrap(); + + // replace newlines with \r\n + let expected = r"GET /.wellknown/wallet/validators.json HTTP/1.1 +Host: nymtech.net +Content-Length: 0 + +" + .replace('\n', "\r\n"); + + assert_eq!(expected, body_as_string); + } +} diff --git a/common/http-requests/src/socks.rs b/common/http-requests/src/socks.rs new file mode 100644 index 0000000000..952ff1fc52 --- /dev/null +++ b/common/http-requests/src/socks.rs @@ -0,0 +1,214 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::error; +use bytecodec::bytes::BytesEncoder; +use bytecodec::bytes::RemainingBytesDecoder; +use bytecodec::io::IoEncodeExt; +use bytecodec::{DecodeExt, Encode}; +use httpcodec::{BodyDecoder, ResponseDecoder}; +use httpcodec::{BodyEncoder, Request, RequestEncoder}; +use nym_service_providers_common::interface::ProviderInterfaceVersion; +use nym_socks5_requests::{SocketData, Socks5ProtocolVersion, Socks5ProviderRequest}; + +pub fn encode_http_request_as_socks_send_request( + provider_interface: ProviderInterfaceVersion, + socks5_protocol: Socks5ProtocolVersion, + conn_id: u64, + request: Request>, + seq: Option, + local_closed: bool, +) -> Result { + // Encode HTTP request as bytes + let mut encoder = RequestEncoder::new(BodyEncoder::new(BytesEncoder::new())); + encoder.start_encoding(request)?; + let mut buf = Vec::new(); + encoder.encode_all(&mut buf)?; + + // Wrap it as SOCKS send request + let request_content = nym_socks5_requests::request::Socks5Request::new_send( + socks5_protocol, + SocketData::new(seq.unwrap_or_default(), conn_id, local_closed, buf), + ); + + // and wrap it in provider request + Ok(Socks5ProviderRequest::new_provider_data( + provider_interface, + request_content, + )) +} + +#[derive(Debug)] +pub struct MixHttpResponse { + // pub connection_id: u64, + // #[deprecated] + // pub is_closed: bool, + pub http_response: httpcodec::Response>, + // #[deprecated] + // pub seq: u64, +} + +impl MixHttpResponse { + pub fn try_from_bytes(b: &[u8]) -> Result { + if b.is_empty() { + Err(error::MixHttpRequestError::EmptySocks5Response) + } else { + let mut decoder = ResponseDecoder::>::default(); + let http_response = decoder.decode_from_bytes(b)?; + + Ok(MixHttpResponse { http_response }) + } + } +} + +// impl TryFrom for MixHttpResponse { +// type Error = error::MixHttpRequestError; +// +// fn try_from(value: Socks5Response) -> Result { +// if let Socks5ResponseContent::NetworkData { content } = value.content { +// content.try_into() +// } else { +// Err(error::MixHttpRequestError::InvalidSocks5Response) +// } +// } +// } +// +// impl TryFrom for MixHttpResponse { +// type Error = error::MixHttpRequestError; +// +// fn try_from(value: SocketData) -> Result { +// if value.data.is_empty() { +// Err(error::MixHttpRequestError::EmptySocks5Response) +// } else { +// let mut decoder = ResponseDecoder::>::default(); +// let http_response = decoder.decode_from_bytes(value.data.as_ref())?; +// +// Ok(MixHttpResponse { +// connection_id: value.header.connection_id, +// is_closed: value.header.local_socket_closed, +// http_response, +// seq: value.header.seq, +// }) +// } +// } +// } + +// pub fn decode_socks_response_as_http_response( +// socks5_response: Socks5Response, +// ) -> Result { +// socks5_response.try_into() +// } +// +// #[cfg(test)] +// mod http_requests_tests { +// use super::*; +// use httpcodec::{HeaderField, HttpVersion, Method, RequestTarget}; +// use nym_service_providers_common::interface::Serializable; +// use nym_socks5_requests::Socks5Response; +// +// fn create_http_get_request() -> Request> { +// let mut request = Request::new( +// Method::new("GET").unwrap(), +// RequestTarget::new("/.wellknown/wallet/validators.json").unwrap(), +// HttpVersion::V1_1, +// b"".to_vec(), +// ); +// let mut headers = request.header_mut(); +// headers.add_field(HeaderField::new("Host", "nymtech.net").unwrap()); +// +// request +// } +// +// fn create_socks5_request_buffer() -> Vec { +// let request = create_http_get_request(); +// let socks5_request = encode_http_request_as_socks_send_request( +// ProviderInterfaceVersion::new_current(), +// Socks5ProtocolVersion::new_current(), +// 99u64, +// request, +// Some(42u64), +// true, +// ) +// .unwrap(); +// socks5_request.into_bytes() +// } +// +// #[test] +// fn request_http_request_content_ok() { +// let buffer = create_socks5_request_buffer(); +// +// // HTTP request string content is as expected +// assert_eq!( +// [71u8, 69u8, 84u8, 32u8, 47u8, 46u8, 119u8, 101u8], +// buffer[19..27] +// ); +// } +// +// /// This test will fail if the framing of the request buffer changes, e.g. when OrderedMessage +// /// changes to have the `index` value as a field, instead of packed with the `data` +// #[test] +// fn request_size_as_expected_ok() { +// let buffer = create_socks5_request_buffer(); +// // println!("{:?}", buffer) // uncomment and run `cargo test -- --nocapture` to view +// +// assert_eq!(108, buffer.len()); // version set to SOCKS5 +// } +// +// #[test] +// fn request_socks5_headers_ok() { +// let buffer = create_socks5_request_buffer(); +// +// assert_eq!(5u8, buffer[0]); // version set to SOCKS5 +// assert_eq!(1u8, buffer[1]); // type is SEND +// assert_eq!(99u8, buffer[9]); // ConnectionId is correct +// assert_eq!(1u8, buffer[10]); // local_closed is true +// } +// +// #[test] +// fn request_ordered_message_ok() { +// let buffer = create_socks5_request_buffer(); +// +// // OrderedMessage index is correct +// assert_eq!(42u8, buffer[18]); +// } +// +// fn create_socks_response() -> Socks5Response { +// // HTTP response is just a string +// let http_response_string = "HTTP/1.1 200 OK\r\nServer: foo/0.0.1\r\n\r\n"; +// +// let data = http_response_string.as_bytes().to_vec(); +// +// // wrap in `NetworkData`, then Socks5Response +// Socks5Response::new( +// Socks5ProtocolVersion::new_current(), +// Socks5ResponseContent::NetworkData { +// content: SocketData::new(42, 99u64, false, data), +// }, +// ) +// } +// +// /// This test will fail is anything in the framing of the socks5_response byte +// /// representation changes +// #[test] +// fn response_byte_size_is_as_expected() { +// let socks5_response = create_socks_response(); +// let buf = socks5_response.into_bytes(); +// +// assert_eq!(57, buf.len()); +// } +// +// #[test] +// fn response_parses() { +// unimplemented!() +// // let socks5_response = create_socks_response(); +// // let response = decode_socks_response_as_http_response(socks5_response).unwrap(); +// // +// // assert_eq!(42u64, response.seq); // OrderedMessage index as expected +// // assert_eq!(HttpVersion::V1_1, response.http_response.http_version()); +// // assert_eq!(200u16, response.http_response.status_code().as_u16()); +// // assert_eq!( +// // "foo/0.0.1", +// // response.http_response.header().get_field("Server").unwrap() +// // ); +// } +// } diff --git a/common/mixnode-common/src/verloc/mod.rs b/common/mixnode-common/src/verloc/mod.rs index 8535b98100..3872f8002e 100644 --- a/common/mixnode-common/src/verloc/mod.rs +++ b/common/mixnode-common/src/verloc/mod.rs @@ -197,12 +197,12 @@ impl VerlocMeasurer { config.packet_timeout, config.connection_timeout, config.delay_between_packets, - shutdown_listener.clone(), + shutdown_listener.clone().named("VerlocPacketSender"), )), packet_listener: Arc::new(PacketListener::new( config.listening_address, Arc::clone(&identity), - shutdown_listener.clone(), + shutdown_listener.clone().named("VerlocPacketListener"), )), shutdown_listener, currently_used_api: 0, @@ -241,7 +241,7 @@ impl VerlocMeasurer { return MeasurementOutcome::Done; } - let mut shutdown_listener = self.shutdown_listener.clone(); + let mut shutdown_listener = self.shutdown_listener.clone().named("VerlocMeasurement"); shutdown_listener.mark_as_success(); for chunk in nodes_to_test.chunks(self.config.tested_nodes_batch_size) { diff --git a/common/mixnode-common/src/verloc/sender.rs b/common/mixnode-common/src/verloc/sender.rs index 665acc3145..8940738bcf 100644 --- a/common/mixnode-common/src/verloc/sender.rs +++ b/common/mixnode-common/src/verloc/sender.rs @@ -83,7 +83,7 @@ impl PacketSender { self: Arc, tested_node: TestedNode, ) -> Result { - let mut shutdown_listener = self.shutdown_listener.clone(); + let mut shutdown_listener = self.shutdown_listener.fork(tested_node.address.to_string()); shutdown_listener.mark_as_success(); let mut conn = match tokio::time::timeout( diff --git a/common/node-tester-utils/Cargo.toml b/common/node-tester-utils/Cargo.toml index 32ec845723..d3e7c1cdf1 100644 --- a/common/node-tester-utils/Cargo.toml +++ b/common/node-tester-utils/Cargo.toml @@ -27,4 +27,4 @@ workspace = true ## wasm-only dependencies [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-utils] -path = "../wasm-utils" +path = "../wasm/utils" diff --git a/common/node-tester-utils/src/lib.rs b/common/node-tester-utils/src/lib.rs index a5e304c584..91d2c7c03f 100644 --- a/common/node-tester-utils/src/lib.rs +++ b/common/node-tester-utils/src/lib.rs @@ -9,6 +9,9 @@ pub mod receiver; pub mod tester; pub use message::{Empty, TestMessage}; +pub use nym_sphinx::{ + chunking::fragment::FragmentIdentifier, params::PacketSize, preparer::PreparedFragment, +}; pub use tester::NodeTester; // it feels wrong to redefine it, but I don't want to import the whole of contract commons just for this one type diff --git a/common/nymsphinx/addressing/Cargo.toml b/common/nymsphinx/addressing/Cargo.toml index c6bc2856e3..4420d7f258 100644 --- a/common/nymsphinx/addressing/Cargo.toml +++ b/common/nymsphinx/addressing/Cargo.toml @@ -15,3 +15,4 @@ thiserror = "1.0.37" [dev-dependencies] rand = "0.7" +nym-crypto = { path = "../../crypto", features = ["rand"] } \ No newline at end of file diff --git a/common/nymsphinx/addressing/src/clients.rs b/common/nymsphinx/addressing/src/clients.rs index a37f15a5fa..a739e7369e 100644 --- a/common/nymsphinx/addressing/src/clients.rs +++ b/common/nymsphinx/addressing/src/clients.rs @@ -39,7 +39,7 @@ pub enum RecipientFormattingError { } // TODO: this should a different home... somewhere, but where? -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq)] pub struct Recipient { client_identity: ClientIdentity, client_encryption_key: ClientEncryptionKey, @@ -226,6 +226,13 @@ impl std::fmt::Display for Recipient { } } +impl std::fmt::Debug for Recipient { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + // use the Display implementation + ::fmt(self, f) + } +} + impl FromStr for Recipient { type Err = RecipientFormattingError; diff --git a/common/nymsphinx/src/receiver.rs b/common/nymsphinx/src/receiver.rs index 631ee5eef0..a756d6b1ba 100644 --- a/common/nymsphinx/src/receiver.rs +++ b/common/nymsphinx/src/receiver.rs @@ -243,7 +243,7 @@ mod message_receiver { ) .unwrap(), layer: Layer::One, - version: "0.8.0-dev".to_string(), + version: "0.8.0-dev".into(), }], ); @@ -263,7 +263,7 @@ mod message_receiver { ) .unwrap(), layer: Layer::Two, - version: "0.8.0-dev".to_string(), + version: "0.8.0-dev".into(), }], ); @@ -283,7 +283,7 @@ mod message_receiver { ) .unwrap(), layer: Layer::Three, - version: "0.8.0-dev".to_string(), + version: "0.8.0-dev".into(), }], ); @@ -303,7 +303,7 @@ mod message_receiver { "EB42xvMFMD5rUCstE2CDazgQQJ22zLv8SPm1Luxni44c", ) .unwrap(), - version: "0.8.0-dev".to_string(), + version: "0.8.0-dev".into(), }], ) } diff --git a/common/socks5/ordered-buffer/src/buffer.rs b/common/socks5/ordered-buffer/src/buffer.rs index 1b7b281727..23bcd13c80 100644 --- a/common/socks5/ordered-buffer/src/buffer.rs +++ b/common/socks5/ordered-buffer/src/buffer.rs @@ -78,6 +78,16 @@ impl OrderedMessageBuffer { Ok(()) } + /// Checks whether the buffer contains enough contiguous regions to read until the specified target sequence. + pub fn can_read_until(&self, target: u64) -> bool { + for seq in self.next_sequence..=target { + if !self.messages.contains_key(&seq) { + return false; + } + } + true + } + /// Returns `Option>` where it's `Some(bytes)` if there is gapless /// ordered data in the buffer, and `None` if the buffer is empty or has /// gaps in the contained data. @@ -110,7 +120,7 @@ impl OrderedMessageBuffer { ); Some(ReadContiguousData { data: contiguous_messages, - last_sequence: seq, + last_sequence: self.next_sequence - 1, }) } } diff --git a/common/socks5/proxy-helpers/src/connection_controller.rs b/common/socks5/proxy-helpers/src/connection_controller.rs index 0d93009626..416b88770f 100644 --- a/common/socks5/proxy-helpers/src/connection_controller.rs +++ b/common/socks5/proxy-helpers/src/connection_controller.rs @@ -171,7 +171,7 @@ impl Controller { if let Some(payload) = active_connection.read_from_buf() { if let Some(closed_at_index) = active_connection.closed_at_index { - if payload.last_sequence > closed_at_index { + if payload.last_sequence >= closed_at_index { active_connection.is_closed = true; } } diff --git a/common/socks5/requests/src/request.rs b/common/socks5/requests/src/request.rs index 530d27e11f..bca0bc25a5 100644 --- a/common/socks5/requests/src/request.rs +++ b/common/socks5/requests/src/request.rs @@ -9,6 +9,7 @@ use nym_service_providers_common::interface::{Serializable, ServiceProviderReque use nym_sphinx_addressing::clients::{Recipient, RecipientFormattingError}; use serde::{Deserialize, Serialize}; use std::convert::TryFrom; +use std::fmt::{Debug, Formatter}; use tap::TapFallible; use thiserror::Error; @@ -75,7 +76,7 @@ impl RequestDeserializationError { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq)] pub struct ConnectRequest { // TODO: is connection_id redundant now? pub conn_id: ConnectionId, @@ -83,6 +84,19 @@ pub struct ConnectRequest { pub return_address: Option, } +impl Debug for ConnectRequest { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ConnectRequest") + .field("conn_id", &self.conn_id) + .field("remote_addr", &self.remote_addr) + .field( + "return_address", + &self.return_address.map(|r| r.to_string()), + ) + .finish() + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct SendRequest { pub data: SocketData, diff --git a/common/socks5/requests/src/response.rs b/common/socks5/requests/src/response.rs index 0415035ac5..e7ea358479 100644 --- a/common/socks5/requests/src/response.rs +++ b/common/socks5/requests/src/response.rs @@ -64,7 +64,7 @@ pub enum ResponseDeserializationError { }, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Socks5Response { pub protocol_version: Socks5ProtocolVersion, pub content: Socks5ResponseContent, diff --git a/common/task/src/manager.rs b/common/task/src/manager.rs index 358534e09b..e9147776b7 100644 --- a/common/task/src/manager.rs +++ b/common/task/src/manager.rs @@ -5,6 +5,7 @@ use std::future::Future; use std::{error::Error, time::Duration}; use futures::{future::pending, FutureExt, SinkExt, StreamExt}; +use log::{log, Level}; use tokio::{ sync::{ mpsc, @@ -23,10 +24,18 @@ pub type SentStatus = Box; pub type StatusSender = futures::channel::mpsc::Sender; pub type StatusReceiver = futures::channel::mpsc::Receiver; +fn try_recover_name(name: &Option) -> String { + if let Some(name) = name { + name.clone() + } else { + "unknown".to_string() + } +} + #[derive(thiserror::Error, Debug)] enum TaskError { - #[error("Task halted unexpectedly")] - UnexpectedHalt, + #[error("Task '{}' halted unexpectedly", try_recover_name(.shutdown_name))] + UnexpectedHalt { shutdown_name: Option }, } // TODO: possibly we should create a `Status` trait instead of reusing `Error` @@ -40,6 +49,9 @@ pub enum TaskStatus { /// shutdown. Keeps track of if task stop unexpectedly, such as in a panic. #[derive(Debug)] pub struct TaskManager { + // optional name assigned to the task manager that all subscribed task clients will inherit + name: Option, + // These channels have the dual purpose of signalling it's time to shutdown, but also to keep // track of which tasks we are still waiting for. notify_tx: watch::Sender<()>, @@ -72,6 +84,7 @@ impl Default for TaskManager { // there is a listener. let (task_status_tx, task_status_rx) = futures::channel::mpsc::channel(128); Self { + name: None, notify_tx, notify_rx: Some(notify_rx), shutdown_timer_secs: DEFAULT_SHUTDOWN_TIMER_SECS, @@ -93,6 +106,12 @@ impl TaskManager { } } + #[must_use] + pub fn named>(mut self, name: S) -> Self { + self.name = Some(name.into()); + self + } + #[cfg(not(target_arch = "wasm32"))] pub async fn catch_interrupt(mut self) -> Result<(), SentError> { let res = crate::wait_for_signal_and_error(&mut self).await; @@ -107,7 +126,7 @@ impl TaskManager { } pub fn subscribe(&self) -> TaskClient { - TaskClient::new( + let task_client = TaskClient::new( self.notify_rx .as_ref() .expect("Unable to subscribe to shutdown notifier that is already shutdown") @@ -115,7 +134,13 @@ impl TaskManager { self.task_return_error_tx.clone(), self.task_drop_tx.clone(), self.task_status_tx.clone(), - ) + ); + + if let Some(name) = &self.name { + task_client.named(format!("{name}-child")) + } else { + task_client + } } pub fn signal_shutdown(&self) -> Result<(), SendError<()>> { @@ -207,8 +232,11 @@ impl TaskManager { /// Listen for shutdown notifications, and can send error and status messages back to the /// `TaskManager` -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct TaskClient { + // optional name assigned to the shutdown handle + name: Option, + // If a shutdown notification has been registered shutdown: bool, @@ -229,7 +257,35 @@ pub struct TaskClient { mode: ClientOperatingMode, } +impl Clone for TaskClient { + fn clone(&self) -> Self { + // make sure to not accidentally overflow the stack if we keep cloning the handle + let name = if let Some(name) = &self.name { + if name != Self::OVERFLOW_NAME && name.len() < Self::MAX_NAME_LENGTH { + Some(format!("{name}-child")) + } else { + Some(Self::OVERFLOW_NAME.to_string()) + } + } else { + None + }; + + TaskClient { + name, + shutdown: self.shutdown, + notify: self.notify.clone(), + return_error: self.return_error.clone(), + drop_error: self.drop_error.clone(), + status_msg: self.status_msg.clone(), + mode: self.mode.clone(), + } + } +} + impl TaskClient { + const MAX_NAME_LENGTH: usize = 128; + const OVERFLOW_NAME: &'static str = "reached maximum TaskClient children name depth"; + #[cfg(not(target_arch = "wasm32"))] const SHUTDOWN_TIMEOUT_WAITING_FOR_SIGNAL_ON_EXIT: Duration = Duration::from_secs(5); @@ -240,6 +296,7 @@ impl TaskClient { status_msg: StatusSender, ) -> TaskClient { TaskClient { + name: None, shutdown: false, notify, return_error, @@ -249,6 +306,41 @@ impl TaskClient { } } + // TODO: not convinced about the name... + pub fn fork>(&self, child_suffix: S) -> Self { + let mut child = self.clone(); + let suffix = child_suffix.into(); + let child_name = if let Some(base) = &self.name { + format!("{base}-{suffix}") + } else { + format!("unknown-{suffix}") + }; + + child.name = Some(child_name); + child + } + + // just a convenience wrapper for including the shutdown name when logging + // I really didn't want to create macros for that... because that seemed like an overkill. + // but I guess it would have resolved needing to call `format!` for additional msg arguments + fn log>(&self, level: Level, msg: S) { + let msg = msg.into(); + + let target = &if let Some(name) = &self.name { + format!("TaskClient-{name}") + } else { + "unnamed-TaskClient".to_string() + }; + + log!(target: target, level, "{msg}") + } + + #[must_use] + pub fn named>(mut self, name: S) -> Self { + self.name = Some(name.into()); + self + } + pub async fn run_future(&mut self, fut: Fut) -> Option where Fut: Future, @@ -267,6 +359,7 @@ impl TaskClient { let (task_drop_tx, _task_drop_rx) = mpsc::unbounded_channel(); let (task_status_tx, _task_status_rx) = futures::channel::mpsc::channel(128); TaskClient { + name: None, shutdown: false, notify: notify_rx, return_error: task_halt_tx, @@ -310,6 +403,7 @@ impl TaskClient { pub async fn recv_timeout(&mut self) { if self.mode.is_dummy() { + #[cfg_attr(target_arch = "wasm32", allow(clippy::needless_return))] return pending().await; } #[cfg(not(target_arch = "wasm32"))] @@ -336,8 +430,9 @@ impl TaskClient { has_changed } Err(err) => { - log::error!("Polling shutdown failed: {err}"); - log::error!("Assuming this means we should shutdown..."); + self.log(Level::Error, format!("Polling shutdown failed: {err}")); + self.log(Level::Error, "Assuming this means we should shutdown..."); + true } } @@ -354,9 +449,11 @@ impl TaskClient { if self.mode.is_dummy() { return; } - log::trace!("Notifying we stopped: {err}"); + + self.log(Level::Trace, format!("Notifying we stopped: {err}")); + if self.return_error.send(err).is_err() { - log::error!("Failed to send back error message"); + self.log(Level::Error, "failed to send back error message"); } } @@ -373,13 +470,20 @@ impl TaskClient { impl Drop for TaskClient { fn drop(&mut self) { if !self.mode.should_signal_on_drop() { + self.log(Level::Debug, "the task client is getting dropped"); return; + } else { + self.log(Level::Info, "the task client is getting dropped"); } + if !self.is_shutdown_poll() { - log::trace!("Notifying stop on unexpected drop"); + self.log(Level::Trace, "Notifying stop on unexpected drop"); + // If we can't send, well then there is not much to do self.drop_error - .send(Box::new(TaskError::UnexpectedHalt)) + .send(Box::new(TaskError::UnexpectedHalt { + shutdown_name: self.name.clone(), + })) .ok(); } } diff --git a/common/topology/Cargo.toml b/common/topology/Cargo.toml index bfe2c98573..e6d35a509c 100644 --- a/common/topology/Cargo.toml +++ b/common/topology/Cargo.toml @@ -17,6 +17,7 @@ log = { workspace = true } rand = { version = "0.7.3", features = ["wasm-bindgen"] } thiserror = "1.0.37" async-trait = { workspace = true, optional = true } +semver = "0.11" ## internal nym-crypto = { path = "../crypto", features = ["sphinx", "outfox"] } diff --git a/common/topology/src/gateway.rs b/common/topology/src/gateway.rs index 9602043e42..04e7d6f45a 100644 --- a/common/topology/src/gateway.rs +++ b/common/topology/src/gateway.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::{filter, NetworkAddress}; +use crate::{filter, NetworkAddress, NodeVersion}; use nym_crypto::asymmetric::{encryption, identity}; use nym_mixnet_contract_common::GatewayBond; use nym_sphinx_addressing::nodes::{NodeIdentity, NymNodeRoutingAddress}; @@ -38,7 +38,7 @@ pub struct Node { pub clients_port: u16, pub identity_key: identity::PublicKey, pub sphinx_key: encryption::PublicKey, // TODO: or nymsphinx::PublicKey? both are x25519 - pub version: String, + pub version: NodeVersion, } impl Node { @@ -83,7 +83,8 @@ impl fmt::Display for Node { impl filter::Versioned for Node { fn version(&self) -> String { - self.version.clone() + // TODO: return semver instead + self.version.to_string() } } @@ -114,7 +115,7 @@ impl<'a> TryFrom<&'a GatewayBond> for Node { clients_port: bond.gateway.clients_port, identity_key: identity::PublicKey::from_base58_string(&bond.gateway.identity_key)?, sphinx_key: encryption::PublicKey::from_base58_string(&bond.gateway.sphinx_key)?, - version: bond.gateway.version.clone(), + version: bond.gateway.version.as_str().into(), }) } } diff --git a/common/topology/src/lib.rs b/common/topology/src/lib.rs index 428efd1056..8c2a06cbfa 100644 --- a/common/topology/src/lib.rs +++ b/common/topology/src/lib.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::filter::VersionFilterable; +pub use error::NymTopologyError; use log::warn; use nym_mixnet_contract_common::mixnode::MixNodeDetails; use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId}; @@ -25,7 +26,38 @@ pub mod random_route_provider; #[cfg(feature = "provider-trait")] pub mod provider_trait; -pub use error::NymTopologyError; +#[cfg(feature = "provider-trait")] +pub use provider_trait::{HardcodedTopologyProvider, TopologyProvider}; + +#[derive(Debug, Default, Clone)] +pub enum NodeVersion { + Explicit(semver::Version), + + #[default] + Unknown, +} + +// this is only implemented for backwards compatibility so we wouldn't need to change everything at once +// (also I intentionally implemented `ToString` as opposed to `Display`) +impl ToString for NodeVersion { + fn to_string(&self) -> String { + match self { + NodeVersion::Explicit(semver) => semver.to_string(), + NodeVersion::Unknown => String::new(), + } + } +} + +// this is also for backwards compat. +impl<'a> From<&'a str> for NodeVersion { + fn from(value: &'a str) -> Self { + if let Ok(semver) = value.parse() { + NodeVersion::Explicit(semver) + } else { + NodeVersion::Unknown + } + } +} #[derive(Debug, Clone)] pub enum NetworkAddress { @@ -390,7 +422,7 @@ mod converting_mixes_to_vec { ) .unwrap(), layer: Layer::One, - version: "0.x.0".to_string(), + version: "0.2.0".into(), }; let node2 = mix::Node { diff --git a/common/topology/src/mix.rs b/common/topology/src/mix.rs index 732999d7e9..bfc4b90344 100644 --- a/common/topology/src/mix.rs +++ b/common/topology/src/mix.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::{filter, NetworkAddress}; +use crate::{filter, NetworkAddress, NodeVersion}; use nym_crypto::asymmetric::{encryption, identity}; pub use nym_mixnet_contract_common::Layer; use nym_mixnet_contract_common::{MixId, MixNodeBond}; @@ -39,7 +39,7 @@ pub struct Node { pub identity_key: identity::PublicKey, pub sphinx_key: encryption::PublicKey, // TODO: or nymsphinx::PublicKey? both are x25519 pub layer: Layer, - pub version: String, + pub version: NodeVersion, } impl Node { @@ -66,7 +66,8 @@ impl Node { impl filter::Versioned for Node { fn version(&self) -> String { - self.version.clone() + // TODO: return semver instead + self.version.to_string() } } @@ -98,7 +99,7 @@ impl<'a> TryFrom<&'a MixNodeBond> for Node { identity_key: identity::PublicKey::from_base58_string(&bond.mix_node.identity_key)?, sphinx_key: encryption::PublicKey::from_base58_string(&bond.mix_node.sphinx_key)?, layer: bond.layer, - version: bond.mix_node.version.clone(), + version: bond.mix_node.version.as_str().into(), }) } } diff --git a/common/wasm-utils/Cargo.toml b/common/wasm-utils/Cargo.toml deleted file mode 100644 index fb4b25c5d8..0000000000 --- a/common/wasm-utils/Cargo.toml +++ /dev/null @@ -1,63 +0,0 @@ -[package] -name = "wasm-utils" -version = "0.1.0" -authors = ["Jedrzej Stuczynski "] -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -futures = { workspace = true } -js-sys = "^0.3.51" -wasm-bindgen = "=0.2.83" -wasm-bindgen-futures = "0.4" -serde = { workspace = true, features = ["derive"], optional = true } -serde-wasm-bindgen = { version = "0.5.0", optional = true } -getrandom = { version="0.2", features=["js"], optional = true } -indexed_db_futures = { version = " 0.3.0", optional = true } -thiserror = { workspace = true, optional = true } - -nym-store-cipher = { path = "../store-cipher", features = ["json"], optional = true } - -# we don't want entire tokio-tungstenite, tungstenite itself is just fine - we just want message and error enums -[dependencies.tungstenite] -version = "0.13" -default-features = false -optional = true - -[dependencies.web-sys] -version = "0.3" -optional = true - -[features] -default = ["sleep"] -sleep = ["web-sys", "web-sys/Window"] -websocket = [ - "getrandom", - "tungstenite", - "web-sys", - "web-sys/BinaryType", - "web-sys/Blob", - "web-sys/CloseEvent", - "web-sys/ErrorEvent", - "web-sys/FileReader", - "web-sys/MessageEvent", - "web-sys/ProgressEvent", - "web-sys/WebSocket", -] -crypto = [ - "web-sys", - "web-sys/Crypto", - "web-sys/CryptoKey", - "web-sys/CryptoKeyPair", - "web-sys/SubtleCrypto", - "web-sys/Window", - "web-sys/WorkerGlobalScope", -] -storage = [ - "indexed_db_futures", - "nym-store-cipher", - "serde", - "serde-wasm-bindgen", - "thiserror" -] diff --git a/common/wasm-utils/src/websocket/mod.rs b/common/wasm-utils/src/websocket/mod.rs deleted file mode 100644 index 08e16217f5..0000000000 --- a/common/wasm-utils/src/websocket/mod.rs +++ /dev/null @@ -1,289 +0,0 @@ -// Copyright 2021 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use crate::websocket::state::State; -use crate::{console_error, console_log}; -use futures::{Sink, Stream}; -use std::cell::RefCell; -use std::collections::VecDeque; -use std::io; -use std::pin::Pin; -use std::rc::Rc; -use std::task::{Context, Poll, Waker}; -use tungstenite::{Error as WsError, Message as WsMessage}; // use tungstenite Message and Error types for easier compatibility with `ClientHandshake` -use wasm_bindgen::closure::Closure; -use wasm_bindgen::JsCast; -use wasm_bindgen::JsValue; -use web_sys::{CloseEvent, ErrorEvent, MessageEvent, WebSocket}; - -mod state; - -// Unfortunately this can't be cleanly done with TryFrom/TryInto traits as both are foreign types -fn try_message_event_into_ws_message(msg_event: MessageEvent) -> Result { - match msg_event.data() { - buf if buf.is_instance_of::() => { - let array = js_sys::Uint8Array::new(&buf); - Ok(WsMessage::Binary(array.to_vec())) - } - blob if blob.is_instance_of::() => { - console_error!("received a blob on the websocket - ignoring it!"); - // we really don't want to bother dealing with Blobs, because it requires juggling filereaders, - // having event handlers to see when they're done, etc. - // + we shouldn't even get one [a blob] to begin with - // considering that our binary mode is (should be) set to array buffer. - Err(WsError::Io(io::Error::from(io::ErrorKind::InvalidInput))) - } - text if text.is_string() => match text.as_string() { - Some(text) => Ok(WsMessage::Text(text)), - None => Err(WsError::Utf8), - }, - // "received a websocket message that is neither a String, ArrayBuffer or a Blob" - _ => Err(WsError::Io(io::Error::from(io::ErrorKind::InvalidInput))), - } -} - -// Safety: when compiled to wasm32 everything is going to be running on a single thread and so there -// is no shared memory right now. -// -// Eventually it should be made `Send` properly. Wakers should probably be replaced with AtomicWaker -// and the item queue put behind an Arc>. -// It might also be worth looking at what https://crates.io/crates/send_wrapper could provide. -// Because I'm not sure Mutex would solve the `Closure` issue. It's the problem for later. -// -// ************************************ -// SUPER IMPORTANT TODO: ONCE WASM IN RUST MATURES AND BECOMES MULTI-THREADED THIS MIGHT -// LEAD TO RUNTIME MEMORY CORRUPTION!! -// ************************************ -// -unsafe impl Send for JSWebsocket {} - -#[derive(Debug)] -#[allow(clippy::upper_case_acronyms)] -pub struct JSWebsocket { - socket: web_sys::WebSocket, - - message_queue: Rc>>>, - - /// Waker of a task wanting to read incoming messages. - stream_waker: Rc>>, - - /// Waker of a task wanting to write to the sink. - sink_waker: Rc>>, - - /// Waker of a sink wanting to close the connection. - close_waker: Rc>>, - - // The callback closures. We need to store them as they will invalidate their - // corresponding JS callback whenever they are dropped, so if we were to - // normally return from `new` then our registered closures will - // raise an exception when invoked. - _on_open: Closure, - _on_error: Closure, - _on_close: Closure, - _on_message: Closure, -} - -impl JSWebsocket { - pub fn new(url: &str) -> Result { - let ws = WebSocket::new(url)?; - // we don't want to ever have to deal with blobs - ws.set_binary_type(web_sys::BinaryType::Arraybuffer); - - let message_queue = Rc::new(RefCell::new(VecDeque::new())); - let message_queue_clone = Rc::clone(&message_queue); - - let stream_waker: Rc>> = Rc::new(RefCell::new(None)); - let stream_waker_clone = Rc::clone(&stream_waker); - let stream_waker_clone2 = Rc::clone(&stream_waker); - - let sink_waker: Rc>> = Rc::new(RefCell::new(None)); - let sink_waker_clone = Rc::clone(&sink_waker); - let sink_waker_clone2 = Rc::clone(&sink_waker); - - let close_waker: Rc>> = Rc::new(RefCell::new(None)); - let close_waker_clone = Rc::clone(&close_waker); - - let on_message = Closure::wrap(Box::new(move |msg_event| { - let ws_message = try_message_event_into_ws_message(msg_event); - message_queue_clone.borrow_mut().push_back(ws_message); - - // if there is a task waiting for messages - wake the executor! - if let Some(waker) = stream_waker_clone.borrow_mut().take() { - waker.wake() - } - }) as Box); - - let url_clone = url.to_string(); - let on_open = Closure::wrap(Box::new(move |_| { - // in case there was a sink send request made before connection was fully established - console_log!("Websocket to {:?} is now open!", url_clone); - - // if there is a task waiting to write messages - wake the executor! - if let Some(waker) = sink_waker_clone.borrow_mut().take() { - waker.wake() - } - - // no need to wake the stream_waker because we won't have any message to send - // immediately anyway. It only makes sense to wake it during on_message (if any) - }) as Box); - - let on_error = Closure::wrap(Box::new(move |e: ErrorEvent| { - console_error!("Websocket error event: {:?}", e); - }) as Box); - - let on_close = Closure::wrap(Box::new(move |e: CloseEvent| { - console_log!("Websocket close event: {:?}", e); - // something was waiting for the close event! - if let Some(waker) = close_waker_clone.borrow_mut().take() { - waker.wake() - } - - // TODO: are waking those sufficient to prevent memory leaks? - if let Some(waker) = stream_waker_clone2.borrow_mut().take() { - waker.wake() - } - - if let Some(waker) = sink_waker_clone2.borrow_mut().take() { - waker.wake() - } - }) as Box); - - ws.set_onmessage(Some(on_message.as_ref().unchecked_ref())); - ws.set_onerror(Some(on_error.as_ref().unchecked_ref())); - ws.set_onopen(Some(on_open.as_ref().unchecked_ref())); - ws.set_onclose(Some(on_close.as_ref().unchecked_ref())); - - Ok(JSWebsocket { - socket: ws, - message_queue, - stream_waker, - sink_waker, - close_waker, - - _on_open: on_open, - _on_error: on_error, - _on_close: on_close, - _on_message: on_message, - }) - } - - pub async fn close(&mut self, code: Option) { - if let Some(code) = code { - self.socket - .close_with_code(code) - .expect("failed to close the socket!"); - } else { - self.socket.close().expect("failed to close the socket!"); - } - } - - fn state(&self) -> State { - self.socket.ready_state().into() - } -} - -impl Drop for JSWebsocket { - fn drop(&mut self) { - match self.state() { - State::Closed | State::Closing => {} // no need to do anything here - _ => self - .socket - .close() - .expect("failed to close WebSocket during drop!"), - } - - self.socket.set_onmessage(None); - self.socket.set_onerror(None); - self.socket.set_onopen(None); - self.socket.set_onclose(None); - } -} - -impl Stream for JSWebsocket { - type Item = Result; - - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - // if there's anything in the internal queue, keep returning that - let ws_message = self.message_queue.borrow_mut().pop_front(); - match ws_message { - Some(message) => Poll::Ready(Some(message)), - None => { - // if connection is closed or closing it means no more useful messages will ever arrive - // and hence we should signal this. - match self.state() { - State::Closing | State::Closed => Poll::Ready(None), - State::Open | State::Connecting => { - // clone the waker to be able to notify the executor once we get a new message - *self.stream_waker.borrow_mut() = Some(cx.waker().clone()); - Poll::Pending - } - } - } - } - } -} - -impl Sink for JSWebsocket { - type Error = WsError; - - fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - match self.state() { - State::Connecting => { - // clone the waker to be able to notify the executor once we get connected - *self.sink_waker.borrow_mut() = Some(cx.waker().clone()); - Poll::Pending - } - - State::Open => Poll::Ready(Ok(())), - State::Closing | State::Closed => Poll::Ready(Err(WsError::AlreadyClosed)), - } - } - - fn start_send(self: Pin<&mut Self>, item: WsMessage) -> Result<(), Self::Error> { - // the only possible errors, per https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send - - // are `INVALID_STATE_ERR` which is when connection is not in open state - - // and `SYNTAX_ERR` which is when data is a string that has unpaired surrogates. This one - // is essentially impossible to happen in rust (assuming wasm_bindgen has done its jobs - // correctly, but even if not, there's nothing we can do ourselves. - - // hence we can map all errors to not open - - match self.state() { - State::Open => match item { - WsMessage::Binary(data) => self.socket.send_with_u8_array(&data), - WsMessage::Text(text) => self.socket.send_with_str(&text), - _ => unreachable!("those are not even exposed by the web_sys API"), - } - .map_err(|_| WsError::Io(io::Error::from(io::ErrorKind::NotConnected))), - - State::Closing | State::Closed => Err(WsError::AlreadyClosed), - State::Connecting => Err(WsError::Io(io::Error::from(io::ErrorKind::NotConnected))), - } - } - - fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { - // TODO: can we/should we do anything more here? - Poll::Ready(Ok(())) - } - - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - match self.state() { - State::Open | State::Connecting => { - // TODO: do we need to wait for closing event here? - *self.close_waker.borrow_mut() = Some(cx.waker().clone()); - - // close inner socket - Poll::Ready(self.socket.close().map_err(|_| todo!())) - } - // if we're already closed, nothing left to do! - State::Closed => Poll::Ready(Ok(())), - State::Closing => { - *self.close_waker.borrow_mut() = Some(cx.waker().clone()); - // wait for the close event... - Poll::Pending - } - } - } -} diff --git a/common/wasm-utils/src/websocket/state.rs b/common/wasm-utils/src/websocket/state.rs deleted file mode 100644 index aee1525141..0000000000 --- a/common/wasm-utils/src/websocket/state.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2021 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use web_sys::WebSocket; - -// convenience wrapper for state values provided by [`web_sys::WebSocket`] -/// The state values correspond to the `readyState` API of the `WebSocket`. -/// See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState) for more details. -#[repr(u16)] -pub(crate) enum State { - Connecting = 0, - Open = 1, - Closing = 2, - Closed = 3, -} - -impl From for State { - fn from(state: u16) -> Self { - match state { - WebSocket::CONNECTING => State::Connecting, - WebSocket::OPEN => State::Open, - WebSocket::CLOSING => State::Closing, - WebSocket::CLOSED => State::Closed, - n => panic!("{n} is not a valid WebSocket state!"), // should we panic here or change it into `TryFrom` instead? - } - } -} diff --git a/common/wasm/client-core/Cargo.toml b/common/wasm/client-core/Cargo.toml new file mode 100644 index 0000000000..82f03573ba --- /dev/null +++ b/common/wasm/client-core/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "wasm-client-core" +authors = ["Jedrzej Stuczynski "] +version = "0.1.0" +edition = "2021" +license = "Apache-2.0" +repository = "https://github.com/nymtech/nym" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-trait = { workspace = true } +js-sys = { workspace = true } +rand = { version = "0.7.3", features = ["wasm-bindgen"] } +serde = { workspace = true, features = ["derive"] } +serde-wasm-bindgen = { workspace = true } +thiserror = { workspace = true } +tsify = { workspace = true, features = ["js"] } +url = { workspace = true } +wasm-bindgen = { workspace = true } +wasm-bindgen-futures = { workspace = true } +zeroize = { workspace = true } + +nym-bandwidth-controller = { path = "../../bandwidth-controller" } +nym-client-core = { path = "../../client-core", default-features = false, features = ["wasm"] } +nym-config = { path = "../../config" } +nym-credential-storage = { path = "../../credential-storage" } +nym-crypto = { path = "../../crypto", features = ["asymmetric", "serde"] } +nym-gateway-client = { path = "../../client-libs/gateway-client", default-features = false, features = ["wasm"] } +nym-sphinx = { path = "../../nymsphinx" } +nym-sphinx-acknowledgements = { path = "../../nymsphinx/acknowledgements", features = ["serde"]} +nym-task = { path = "../../task" } +nym-topology = { path = "../../topology" } +nym-validator-client = { path = "../../client-libs/validator-client", default-features = false } +wasm-utils = { path = "../utils" } +wasm-storage = { path = "../storage" } + + +# The `console_error_panic_hook` crate provides better debugging of panics by +# logging them with `console.error`. This is great for development, but requires +# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for +# code size when deploying. +console_error_panic_hook = { version = "0.1", optional = true } + +[features] +default = ["console_error_panic_hook"] \ No newline at end of file diff --git a/clients/webassembly/src/client/config.rs b/common/wasm/client-core/src/config/mod.rs similarity index 72% rename from clients/webassembly/src/client/config.rs rename to common/wasm/client-core/src/config/mod.rs index f63d1456ac..429fae6400 100644 --- a/clients/webassembly/src/client/config.rs +++ b/common/wasm/client-core/src/config/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2022-2023 - Nym Technologies SA +// Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 // due to expansion of #[wasm_bindgen] macro on `Debug` Config struct @@ -6,342 +6,90 @@ // another issue due to #[wasm_bindgen] and `Copy` trait #![allow(dropping_copy_types)] -use nym_client_core::config::{ - Acknowledgements as ConfigAcknowledgements, Config as BaseClientConfig, - CoverTraffic as ConfigCoverTraffic, DebugConfig as ConfigDebug, - GatewayConnection as ConfigGatewayConnection, ReplySurbs as ConfigReplySurbs, - Topology as ConfigTopology, Traffic as ConfigTraffic, -}; +use crate::error::WasmCoreError; +use nym_config::helpers::OptionalSet; use nym_sphinx::params::{PacketSize, PacketType}; use serde::{Deserialize, Serialize}; use std::time::Duration; use wasm_bindgen::prelude::*; -#[wasm_bindgen] -#[derive(Debug, Deserialize, PartialEq, Serialize)] -#[serde(deny_unknown_fields)] -pub struct Config { - pub(crate) base: BaseClientConfig, +pub mod r#override; + +pub use nym_client_core::config::{ + Acknowledgements as ConfigAcknowledgements, Config as BaseClientConfig, + CoverTraffic as ConfigCoverTraffic, DebugConfig as ConfigDebug, + GatewayConnection as ConfigGatewayConnection, ReplySurbs as ConfigReplySurbs, + Topology as ConfigTopology, Traffic as ConfigTraffic, +}; + +pub fn new_base_client_config( + id: String, + version: String, + nym_api: Option, + nyxd: Option, + debug: Option, +) -> Result { + let nym_api_url = match nym_api { + Some(raw) => Some( + raw.parse() + .map_err(|source| WasmCoreError::MalformedUrl { raw, source })?, + ), + None => None, + }; + + let nyxd_url = match nyxd { + Some(raw) => Some( + raw.parse() + .map_err(|source| WasmCoreError::MalformedUrl { raw, source })?, + ), + None => None, + }; + + Ok(BaseClientConfig::new(id, version) + .with_optional( + BaseClientConfig::with_custom_nym_apis, + nym_api_url.map(|u| vec![u]), + ) + .with_optional( + BaseClientConfig::with_custom_nyxd, + nyxd_url.map(|u| vec![u]), + ) + .with_debug_config(debug.map(Into::into).unwrap_or_default())) } #[wasm_bindgen] -impl Config { - #[wasm_bindgen(constructor)] - pub fn new(id: String, validator_server: String, debug: Option) -> Self { - Config { - base: BaseClientConfig::new(id, env!("CARGO_PKG_VERSION").to_string()) - .with_custom_nyxd(vec![validator_server - .parse() - .expect("provided url was malformed")]) - .with_debug_config(debug.map(Into::into).unwrap_or_default()), - } - } - - pub(crate) fn new_tester_config>(id: S) -> Self { - Config { - base: BaseClientConfig::new(id.into(), env!("CARGO_PKG_VERSION").to_string()) - .with_disabled_credentials(true) - .with_disabled_cover_traffic(true) - .with_disabled_topology_refresh(true), - } - } +pub fn default_debug() -> DebugWasm { + ConfigDebug::default().into() } +#[wasm_bindgen(js_name = defaultDebug)] +pub fn default_debug_obj() -> JsValue { + let dbg = default_debug(); + serde_wasm_bindgen::to_value(&dbg) + .expect("our 'DebugWasm' struct should have had a correctly defined serde implementation") +} + +/// A client configuration in which no cover traffic will be sent, +/// in either the main distribution or the secondary traffic stream. #[wasm_bindgen] -#[derive(Debug, Copy, Clone)] -pub struct TrafficWasm { - /// The parameter of Poisson distribution determining how long, on average, - /// sent packet is going to be delayed at any given mix node. - /// So for a packet going through three mix nodes, on average, it will take three times this value - /// until the packet reaches its destination. - pub average_packet_delay_ms: u64, - - /// The parameter of Poisson distribution determining how long, on average, - /// it is going to take another 'real traffic stream' message to be sent. - /// If no real packets are available and cover traffic is enabled, - /// a loop cover message is sent instead in order to preserve the rate. - pub message_sending_average_delay_ms: u64, - - /// Controls whether the main packet stream constantly produces packets according to the predefined - /// poisson distribution. - pub disable_main_poisson_packet_distribution: bool, - - /// Controls whether the sent sphinx packet use the NON-DEFAULT bigger size. - pub use_extended_packet_size: bool, - - /// Controls whether the sent packets should use outfox as opposed to the default sphinx. - pub use_outfox: bool, +pub fn no_cover_debug() -> DebugWasm { + let mut cfg = ConfigDebug::default(); + cfg.traffic.disable_main_poisson_packet_distribution = true; + cfg.cover_traffic.disable_loop_cover_traffic_stream = true; + cfg.into() } -impl From for ConfigTraffic { - fn from(traffic: TrafficWasm) -> Self { - let use_extended_packet_size = traffic - .use_extended_packet_size - .then(|| PacketSize::ExtendedPacket32); - - let packet_type = if traffic.use_outfox { - PacketType::Outfox - } else { - PacketType::Mix - }; - - ConfigTraffic { - average_packet_delay: Duration::from_millis(traffic.average_packet_delay_ms), - message_sending_average_delay: Duration::from_millis( - traffic.message_sending_average_delay_ms, - ), - disable_main_poisson_packet_distribution: traffic - .disable_main_poisson_packet_distribution, - primary_packet_size: PacketSize::RegularPacket, - secondary_packet_size: use_extended_packet_size, - packet_type, - } - } -} - -impl From for TrafficWasm { - fn from(traffic: ConfigTraffic) -> Self { - TrafficWasm { - average_packet_delay_ms: traffic.average_packet_delay.as_millis() as u64, - message_sending_average_delay_ms: traffic.message_sending_average_delay.as_millis() - as u64, - disable_main_poisson_packet_distribution: traffic - .disable_main_poisson_packet_distribution, - use_extended_packet_size: traffic.secondary_packet_size.is_some(), - use_outfox: traffic.packet_type == PacketType::Outfox, - } - } -} - -#[wasm_bindgen] -#[derive(Debug, Copy, Clone)] -pub struct CoverTrafficWasm { - /// The parameter of Poisson distribution determining how long, on average, - /// it is going to take for another loop cover traffic message to be sent. - pub loop_cover_traffic_average_delay_ms: u64, - - /// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic. - /// Only applicable if `secondary_packet_size` is enabled. - pub cover_traffic_primary_size_ratio: f64, - - /// Controls whether the dedicated loop cover traffic stream should be enabled. - /// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay]) - pub disable_loop_cover_traffic_stream: bool, -} - -impl From for ConfigCoverTraffic { - fn from(cover_traffic: CoverTrafficWasm) -> Self { - ConfigCoverTraffic { - loop_cover_traffic_average_delay: Duration::from_millis( - cover_traffic.loop_cover_traffic_average_delay_ms, - ), - cover_traffic_primary_size_ratio: cover_traffic.cover_traffic_primary_size_ratio, - disable_loop_cover_traffic_stream: cover_traffic.disable_loop_cover_traffic_stream, - } - } -} - -impl From for CoverTrafficWasm { - fn from(cover_traffic: ConfigCoverTraffic) -> Self { - CoverTrafficWasm { - loop_cover_traffic_average_delay_ms: cover_traffic - .loop_cover_traffic_average_delay - .as_millis() as u64, - cover_traffic_primary_size_ratio: cover_traffic.cover_traffic_primary_size_ratio, - disable_loop_cover_traffic_stream: cover_traffic.disable_loop_cover_traffic_stream, - } - } -} - -#[wasm_bindgen] -#[derive(Debug, Copy, Clone)] -pub struct GatewayConnectionWasm { - /// How long we're willing to wait for a response to a message sent to the gateway, - /// before giving up on it. - pub gateway_response_timeout_ms: u64, -} - -impl From for ConfigGatewayConnection { - fn from(gateway_connection: GatewayConnectionWasm) -> Self { - ConfigGatewayConnection { - gateway_response_timeout: Duration::from_millis( - gateway_connection.gateway_response_timeout_ms, - ), - } - } -} - -impl From for GatewayConnectionWasm { - fn from(gateway_connection: ConfigGatewayConnection) -> Self { - GatewayConnectionWasm { - gateway_response_timeout_ms: gateway_connection.gateway_response_timeout.as_millis() - as u64, - } - } -} - -#[wasm_bindgen] -#[derive(Debug, Copy, Clone)] -pub struct AcknowledgementsWasm { - /// The parameter of Poisson distribution determining how long, on average, - /// sent acknowledgement is going to be delayed at any given mix node. - /// So for an ack going through three mix nodes, on average, it will take three times this value - /// until the packet reaches its destination. - pub average_ack_delay_ms: u64, - - /// Value multiplied with the expected round trip time of an acknowledgement packet before - /// it is assumed it was lost and retransmission of the data packet happens. - /// In an ideal network with 0 latency, this value would have been 1. - pub ack_wait_multiplier: f64, - - /// Value added to the expected round trip time of an acknowledgement packet before - /// it is assumed it was lost and retransmission of the data packet happens. - /// In an ideal network with 0 latency, this value would have been 0. - pub ack_wait_addition_ms: u64, -} - -impl From for ConfigAcknowledgements { - fn from(acknowledgements: AcknowledgementsWasm) -> Self { - ConfigAcknowledgements { - average_ack_delay: Duration::from_millis(acknowledgements.average_ack_delay_ms), - ack_wait_multiplier: acknowledgements.ack_wait_multiplier, - ack_wait_addition: Duration::from_millis(acknowledgements.ack_wait_addition_ms), - } - } -} - -impl From for AcknowledgementsWasm { - fn from(acknowledgements: ConfigAcknowledgements) -> Self { - AcknowledgementsWasm { - average_ack_delay_ms: acknowledgements.average_ack_delay.as_millis() as u64, - ack_wait_multiplier: acknowledgements.ack_wait_multiplier, - ack_wait_addition_ms: acknowledgements.ack_wait_addition.as_millis() as u64, - } - } -} - -#[wasm_bindgen] -#[derive(Debug, Copy, Clone)] -pub struct TopologyWasm { - /// The uniform delay every which clients are querying the directory server - /// to try to obtain a compatible network topology to send sphinx packets through. - pub topology_refresh_rate_ms: u64, - - /// During topology refresh, test packets are sent through every single possible network - /// path. This timeout determines waiting period until it is decided that the packet - /// did not reach its destination. - pub topology_resolution_timeout_ms: u64, - - /// Specifies whether the client should not refresh the network topology after obtaining - /// the first valid instance. - /// Supersedes `topology_refresh_rate_ms`. - pub disable_refreshing: bool, -} - -impl From for ConfigTopology { - fn from(topology: TopologyWasm) -> Self { - ConfigTopology { - topology_refresh_rate: Duration::from_millis(topology.topology_refresh_rate_ms), - topology_resolution_timeout: Duration::from_millis( - topology.topology_resolution_timeout_ms, - ), - disable_refreshing: topology.disable_refreshing, - topology_structure: Default::default(), - } - } -} - -impl From for TopologyWasm { - fn from(topology: ConfigTopology) -> Self { - TopologyWasm { - topology_refresh_rate_ms: topology.topology_refresh_rate.as_millis() as u64, - topology_resolution_timeout_ms: topology.topology_resolution_timeout.as_millis() as u64, - disable_refreshing: topology.disable_refreshing, - } - } -} - -#[wasm_bindgen] -#[derive(Debug, Copy, Clone)] -pub struct ReplySurbsWasm { - /// Defines the minimum number of reply surbs the client wants to keep in its storage at all times. - /// It can only allow to go below that value if its to request additional reply surbs. - pub minimum_reply_surb_storage_threshold: usize, - - /// Defines the maximum number of reply surbs the client wants to keep in its storage at any times. - pub maximum_reply_surb_storage_threshold: usize, - - /// Defines the minimum number of reply surbs the client would request. - pub minimum_reply_surb_request_size: u32, - - /// Defines the maximum number of reply surbs the client would request. - pub maximum_reply_surb_request_size: u32, - - /// Defines the maximum number of reply surbs a remote party is allowed to request from this client at once. - pub maximum_allowed_reply_surb_request_size: u32, - - /// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking - /// for more even though in theory they wouldn't need to. - pub maximum_reply_surb_rerequest_waiting_period_ms: u64, - - /// Defines maximum amount of time the client is going to wait for reply surbs before - /// deciding it's never going to get them and would drop all pending messages - pub maximum_reply_surb_drop_waiting_period_ms: u64, - - /// Defines maximum amount of time given reply surb is going to be valid for. - /// This is going to be superseded by key rotation once implemented. - pub maximum_reply_surb_age_ms: u64, - - /// Defines maximum amount of time given reply key is going to be valid for. - /// This is going to be superseded by key rotation once implemented. - pub maximum_reply_key_age_ms: u64, -} - -impl From for ConfigReplySurbs { - fn from(reply_surbs: ReplySurbsWasm) -> Self { - ConfigReplySurbs { - minimum_reply_surb_storage_threshold: reply_surbs.minimum_reply_surb_storage_threshold, - maximum_reply_surb_storage_threshold: reply_surbs.maximum_reply_surb_storage_threshold, - minimum_reply_surb_request_size: reply_surbs.minimum_reply_surb_request_size, - maximum_reply_surb_request_size: reply_surbs.maximum_reply_surb_request_size, - maximum_allowed_reply_surb_request_size: reply_surbs - .maximum_allowed_reply_surb_request_size, - maximum_reply_surb_rerequest_waiting_period: Duration::from_millis( - reply_surbs.maximum_reply_surb_rerequest_waiting_period_ms, - ), - maximum_reply_surb_drop_waiting_period: Duration::from_millis( - reply_surbs.maximum_reply_surb_drop_waiting_period_ms, - ), - maximum_reply_surb_age: Duration::from_millis(reply_surbs.maximum_reply_surb_age_ms), - maximum_reply_key_age: Duration::from_millis(reply_surbs.maximum_reply_key_age_ms), - } - } -} - -impl From for ReplySurbsWasm { - fn from(reply_surbs: ConfigReplySurbs) -> Self { - ReplySurbsWasm { - minimum_reply_surb_storage_threshold: reply_surbs.minimum_reply_surb_storage_threshold, - maximum_reply_surb_storage_threshold: reply_surbs.maximum_reply_surb_storage_threshold, - minimum_reply_surb_request_size: reply_surbs.minimum_reply_surb_request_size, - maximum_reply_surb_request_size: reply_surbs.maximum_reply_surb_request_size, - maximum_allowed_reply_surb_request_size: reply_surbs - .maximum_allowed_reply_surb_request_size, - maximum_reply_surb_rerequest_waiting_period_ms: reply_surbs - .maximum_reply_surb_rerequest_waiting_period - .as_millis() as u64, - maximum_reply_surb_drop_waiting_period_ms: reply_surbs - .maximum_reply_surb_drop_waiting_period - .as_millis() as u64, - maximum_reply_surb_age_ms: reply_surbs.maximum_reply_surb_age.as_millis() as u64, - maximum_reply_key_age_ms: reply_surbs.maximum_reply_key_age.as_millis() as u64, - } - } +#[wasm_bindgen(js_name = noCoverDebug)] +pub fn no_cover_debug_obj() -> JsValue { + let dbg = no_cover_debug(); + serde_wasm_bindgen::to_value(&dbg) + .expect("our 'DebugWasm' struct should have had a correctly defined serde implementation") } // just a helper structure to more easily pass through the JS boundary -#[wasm_bindgen] -#[derive(Debug, Copy, Clone)] +#[wasm_bindgen(inspectable)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] pub struct DebugWasm { /// Defines all configuration options related to traffic streams. pub traffic: TrafficWasm, @@ -362,6 +110,12 @@ pub struct DebugWasm { pub reply_surbs: ReplySurbsWasm, } +impl Default for DebugWasm { + fn default() -> Self { + ConfigDebug::default().into() + } +} + impl From for ConfigDebug { fn from(debug: DebugWasm) -> Self { ConfigDebug { @@ -388,7 +142,340 @@ impl From for DebugWasm { } } -#[wasm_bindgen] -pub fn default_debug() -> DebugWasm { - ConfigDebug::default().into() +#[wasm_bindgen(inspectable)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct TrafficWasm { + /// The parameter of Poisson distribution determining how long, on average, + /// sent packet is going to be delayed at any given mix node. + /// So for a packet going through three mix nodes, on average, it will take three times this value + /// until the packet reaches its destination. + pub average_packet_delay_ms: u32, + + /// The parameter of Poisson distribution determining how long, on average, + /// it is going to take another 'real traffic stream' message to be sent. + /// If no real packets are available and cover traffic is enabled, + /// a loop cover message is sent instead in order to preserve the rate. + pub message_sending_average_delay_ms: u32, + + /// Controls whether the main packet stream constantly produces packets according to the predefined + /// poisson distribution. + pub disable_main_poisson_packet_distribution: bool, + + /// Controls whether the sent sphinx packet use the NON-DEFAULT bigger size. + pub use_extended_packet_size: bool, + + /// Controls whether the sent packets should use outfox as opposed to the default sphinx. + pub use_outfox: bool, +} + +impl Default for TrafficWasm { + fn default() -> Self { + ConfigTraffic::default().into() + } +} + +impl From for ConfigTraffic { + fn from(traffic: TrafficWasm) -> Self { + let use_extended_packet_size = traffic + .use_extended_packet_size + .then_some(PacketSize::ExtendedPacket32); + + let packet_type = if traffic.use_outfox { + PacketType::Outfox + } else { + PacketType::Mix + }; + + ConfigTraffic { + average_packet_delay: Duration::from_millis(traffic.average_packet_delay_ms as u64), + message_sending_average_delay: Duration::from_millis( + traffic.message_sending_average_delay_ms as u64, + ), + disable_main_poisson_packet_distribution: traffic + .disable_main_poisson_packet_distribution, + primary_packet_size: PacketSize::RegularPacket, + secondary_packet_size: use_extended_packet_size, + packet_type, + } + } +} + +impl From for TrafficWasm { + fn from(traffic: ConfigTraffic) -> Self { + TrafficWasm { + average_packet_delay_ms: traffic.average_packet_delay.as_millis() as u32, + message_sending_average_delay_ms: traffic.message_sending_average_delay.as_millis() + as u32, + disable_main_poisson_packet_distribution: traffic + .disable_main_poisson_packet_distribution, + use_extended_packet_size: traffic.secondary_packet_size.is_some(), + use_outfox: traffic.packet_type == PacketType::Outfox, + } + } +} + +#[wasm_bindgen(inspectable)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct CoverTrafficWasm { + /// The parameter of Poisson distribution determining how long, on average, + /// it is going to take for another loop cover traffic message to be sent. + pub loop_cover_traffic_average_delay_ms: u32, + + /// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic. + /// Only applicable if `secondary_packet_size` is enabled. + pub cover_traffic_primary_size_ratio: f64, + + /// Controls whether the dedicated loop cover traffic stream should be enabled. + /// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay]) + pub disable_loop_cover_traffic_stream: bool, +} + +impl Default for CoverTrafficWasm { + fn default() -> Self { + ConfigCoverTraffic::default().into() + } +} + +impl From for ConfigCoverTraffic { + fn from(cover_traffic: CoverTrafficWasm) -> Self { + ConfigCoverTraffic { + loop_cover_traffic_average_delay: Duration::from_millis( + cover_traffic.loop_cover_traffic_average_delay_ms as u64, + ), + cover_traffic_primary_size_ratio: cover_traffic.cover_traffic_primary_size_ratio, + disable_loop_cover_traffic_stream: cover_traffic.disable_loop_cover_traffic_stream, + } + } +} + +impl From for CoverTrafficWasm { + fn from(cover_traffic: ConfigCoverTraffic) -> Self { + CoverTrafficWasm { + loop_cover_traffic_average_delay_ms: cover_traffic + .loop_cover_traffic_average_delay + .as_millis() as u32, + cover_traffic_primary_size_ratio: cover_traffic.cover_traffic_primary_size_ratio, + disable_loop_cover_traffic_stream: cover_traffic.disable_loop_cover_traffic_stream, + } + } +} + +#[wasm_bindgen(inspectable)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct GatewayConnectionWasm { + /// How long we're willing to wait for a response to a message sent to the gateway, + /// before giving up on it. + pub gateway_response_timeout_ms: u32, +} + +impl Default for GatewayConnectionWasm { + fn default() -> Self { + ConfigGatewayConnection::default().into() + } +} + +impl From for ConfigGatewayConnection { + fn from(gateway_connection: GatewayConnectionWasm) -> Self { + ConfigGatewayConnection { + gateway_response_timeout: Duration::from_millis( + gateway_connection.gateway_response_timeout_ms as u64, + ), + } + } +} + +impl From for GatewayConnectionWasm { + fn from(gateway_connection: ConfigGatewayConnection) -> Self { + GatewayConnectionWasm { + gateway_response_timeout_ms: gateway_connection.gateway_response_timeout.as_millis() + as u32, + } + } +} + +#[wasm_bindgen(inspectable)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct AcknowledgementsWasm { + /// The parameter of Poisson distribution determining how long, on average, + /// sent acknowledgement is going to be delayed at any given mix node. + /// So for an ack going through three mix nodes, on average, it will take three times this value + /// until the packet reaches its destination. + pub average_ack_delay_ms: u32, + + /// Value multiplied with the expected round trip time of an acknowledgement packet before + /// it is assumed it was lost and retransmission of the data packet happens. + /// In an ideal network with 0 latency, this value would have been 1. + pub ack_wait_multiplier: f64, + + /// Value added to the expected round trip time of an acknowledgement packet before + /// it is assumed it was lost and retransmission of the data packet happens. + /// In an ideal network with 0 latency, this value would have been 0. + pub ack_wait_addition_ms: u32, +} + +impl Default for AcknowledgementsWasm { + fn default() -> Self { + ConfigAcknowledgements::default().into() + } +} + +impl From for ConfigAcknowledgements { + fn from(acknowledgements: AcknowledgementsWasm) -> Self { + ConfigAcknowledgements { + average_ack_delay: Duration::from_millis(acknowledgements.average_ack_delay_ms as u64), + ack_wait_multiplier: acknowledgements.ack_wait_multiplier, + ack_wait_addition: Duration::from_millis(acknowledgements.ack_wait_addition_ms as u64), + } + } +} + +impl From for AcknowledgementsWasm { + fn from(acknowledgements: ConfigAcknowledgements) -> Self { + AcknowledgementsWasm { + average_ack_delay_ms: acknowledgements.average_ack_delay.as_millis() as u32, + ack_wait_multiplier: acknowledgements.ack_wait_multiplier, + ack_wait_addition_ms: acknowledgements.ack_wait_addition.as_millis() as u32, + } + } +} + +#[wasm_bindgen(inspectable)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct TopologyWasm { + /// The uniform delay every which clients are querying the directory server + /// to try to obtain a compatible network topology to send sphinx packets through. + pub topology_refresh_rate_ms: u32, + + /// During topology refresh, test packets are sent through every single possible network + /// path. This timeout determines waiting period until it is decided that the packet + /// did not reach its destination. + pub topology_resolution_timeout_ms: u32, + + /// Specifies whether the client should not refresh the network topology after obtaining + /// the first valid instance. + /// Supersedes `topology_refresh_rate_ms`. + pub disable_refreshing: bool, +} + +impl Default for TopologyWasm { + fn default() -> Self { + ConfigTopology::default().into() + } +} + +impl From for ConfigTopology { + fn from(topology: TopologyWasm) -> Self { + ConfigTopology { + topology_refresh_rate: Duration::from_millis(topology.topology_refresh_rate_ms as u64), + topology_resolution_timeout: Duration::from_millis( + topology.topology_resolution_timeout_ms as u64, + ), + disable_refreshing: topology.disable_refreshing, + topology_structure: Default::default(), + } + } +} + +impl From for TopologyWasm { + fn from(topology: ConfigTopology) -> Self { + TopologyWasm { + topology_refresh_rate_ms: topology.topology_refresh_rate.as_millis() as u32, + topology_resolution_timeout_ms: topology.topology_resolution_timeout.as_millis() as u32, + disable_refreshing: topology.disable_refreshing, + } + } +} + +#[wasm_bindgen(inspectable)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct ReplySurbsWasm { + /// Defines the minimum number of reply surbs the client wants to keep in its storage at all times. + /// It can only allow to go below that value if its to request additional reply surbs. + pub minimum_reply_surb_storage_threshold: usize, + + /// Defines the maximum number of reply surbs the client wants to keep in its storage at any times. + pub maximum_reply_surb_storage_threshold: usize, + + /// Defines the minimum number of reply surbs the client would request. + pub minimum_reply_surb_request_size: u32, + + /// Defines the maximum number of reply surbs the client would request. + pub maximum_reply_surb_request_size: u32, + + /// Defines the maximum number of reply surbs a remote party is allowed to request from this client at once. + pub maximum_allowed_reply_surb_request_size: u32, + + /// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking + /// for more even though in theory they wouldn't need to. + pub maximum_reply_surb_rerequest_waiting_period_ms: u32, + + /// Defines maximum amount of time the client is going to wait for reply surbs before + /// deciding it's never going to get them and would drop all pending messages + pub maximum_reply_surb_drop_waiting_period_ms: u32, + + /// Defines maximum amount of time given reply surb is going to be valid for. + /// This is going to be superseded by key rotation once implemented. + pub maximum_reply_surb_age_ms: u32, + + /// Defines maximum amount of time given reply key is going to be valid for. + /// This is going to be superseded by key rotation once implemented. + pub maximum_reply_key_age_ms: u32, +} + +impl Default for ReplySurbsWasm { + fn default() -> Self { + ConfigReplySurbs::default().into() + } +} + +impl From for ConfigReplySurbs { + fn from(reply_surbs: ReplySurbsWasm) -> Self { + ConfigReplySurbs { + minimum_reply_surb_storage_threshold: reply_surbs.minimum_reply_surb_storage_threshold, + maximum_reply_surb_storage_threshold: reply_surbs.maximum_reply_surb_storage_threshold, + minimum_reply_surb_request_size: reply_surbs.minimum_reply_surb_request_size, + maximum_reply_surb_request_size: reply_surbs.maximum_reply_surb_request_size, + maximum_allowed_reply_surb_request_size: reply_surbs + .maximum_allowed_reply_surb_request_size, + maximum_reply_surb_rerequest_waiting_period: Duration::from_millis( + reply_surbs.maximum_reply_surb_rerequest_waiting_period_ms as u64, + ), + maximum_reply_surb_drop_waiting_period: Duration::from_millis( + reply_surbs.maximum_reply_surb_drop_waiting_period_ms as u64, + ), + maximum_reply_surb_age: Duration::from_millis( + reply_surbs.maximum_reply_surb_age_ms as u64, + ), + maximum_reply_key_age: Duration::from_millis( + reply_surbs.maximum_reply_key_age_ms as u64, + ), + } + } +} + +impl From for ReplySurbsWasm { + fn from(reply_surbs: ConfigReplySurbs) -> Self { + ReplySurbsWasm { + minimum_reply_surb_storage_threshold: reply_surbs.minimum_reply_surb_storage_threshold, + maximum_reply_surb_storage_threshold: reply_surbs.maximum_reply_surb_storage_threshold, + minimum_reply_surb_request_size: reply_surbs.minimum_reply_surb_request_size, + maximum_reply_surb_request_size: reply_surbs.maximum_reply_surb_request_size, + maximum_allowed_reply_surb_request_size: reply_surbs + .maximum_allowed_reply_surb_request_size, + maximum_reply_surb_rerequest_waiting_period_ms: reply_surbs + .maximum_reply_surb_rerequest_waiting_period + .as_millis() as u32, + maximum_reply_surb_drop_waiting_period_ms: reply_surbs + .maximum_reply_surb_drop_waiting_period + .as_millis() as u32, + maximum_reply_surb_age_ms: reply_surbs.maximum_reply_surb_age.as_millis() as u32, + maximum_reply_key_age_ms: reply_surbs.maximum_reply_key_age.as_millis() as u32, + } + } } diff --git a/common/wasm/client-core/src/config/override.rs b/common/wasm/client-core/src/config/override.rs new file mode 100644 index 0000000000..20f3f0cf2a --- /dev/null +++ b/common/wasm/client-core/src/config/override.rs @@ -0,0 +1,334 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use super::{ + AcknowledgementsWasm, CoverTrafficWasm, DebugWasm, GatewayConnectionWasm, ReplySurbsWasm, + TopologyWasm, TrafficWasm, +}; +use crate::config::ConfigDebug; +use serde::{Deserialize, Serialize}; +use tsify::Tsify; + +// just a helper structure to more easily pass through the JS boundary +#[derive(Tsify, Debug, Copy, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct DebugWasmOverride { + /// Defines all configuration options related to traffic streams. + #[tsify(optional)] + pub traffic: Option, + + /// Defines all configuration options related to cover traffic stream(s). + #[tsify(optional)] + pub cover_traffic: Option, + + /// Defines all configuration options related to the gateway connection. + #[tsify(optional)] + pub gateway_connection: Option, + + /// Defines all configuration options related to acknowledgements, such as delays or wait timeouts. + #[tsify(optional)] + pub acknowledgements: Option, + + /// Defines all configuration options related topology, such as refresh rates or timeouts. + #[tsify(optional)] + pub topology: Option, + + /// Defines all configuration options related to reply SURBs. + #[tsify(optional)] + pub reply_surbs: Option, +} + +impl From for DebugWasm { + fn from(value: DebugWasmOverride) -> Self { + DebugWasm { + traffic: value.traffic.map(Into::into).unwrap_or_default(), + cover_traffic: value.cover_traffic.map(Into::into).unwrap_or_default(), + gateway_connection: value.gateway_connection.map(Into::into).unwrap_or_default(), + acknowledgements: value.acknowledgements.map(Into::into).unwrap_or_default(), + topology: value.topology.map(Into::into).unwrap_or_default(), + reply_surbs: value.reply_surbs.map(Into::into).unwrap_or_default(), + } + } +} + +impl From for ConfigDebug { + fn from(value: DebugWasmOverride) -> Self { + let debug_wasm: DebugWasm = value.into(); + debug_wasm.into() + } +} + +#[derive(Tsify, Debug, Copy, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct TrafficWasmOverride { + /// The parameter of Poisson distribution determining how long, on average, + /// sent packet is going to be delayed at any given mix node. + /// So for a packet going through three mix nodes, on average, it will take three times this value + /// until the packet reaches its destination. + #[tsify(optional)] + pub average_packet_delay_ms: Option, + + /// The parameter of Poisson distribution determining how long, on average, + /// it is going to take another 'real traffic stream' message to be sent. + /// If no real packets are available and cover traffic is enabled, + /// a loop cover message is sent instead in order to preserve the rate. + #[tsify(optional)] + pub message_sending_average_delay_ms: Option, + + /// Controls whether the main packet stream constantly produces packets according to the predefined + /// poisson distribution. + #[tsify(optional)] + pub disable_main_poisson_packet_distribution: Option, + + /// Controls whether the sent sphinx packet use the NON-DEFAULT bigger size. + #[tsify(optional)] + pub use_extended_packet_size: Option, + + /// Controls whether the sent packets should use outfox as opposed to the default sphinx. + #[tsify(optional)] + pub use_outfox: Option, +} + +impl From for TrafficWasm { + fn from(value: TrafficWasmOverride) -> Self { + let def = TrafficWasm::default(); + + TrafficWasm { + average_packet_delay_ms: value + .average_packet_delay_ms + .unwrap_or(def.average_packet_delay_ms), + message_sending_average_delay_ms: value + .message_sending_average_delay_ms + .unwrap_or(def.message_sending_average_delay_ms), + disable_main_poisson_packet_distribution: value + .disable_main_poisson_packet_distribution + .unwrap_or(def.disable_main_poisson_packet_distribution), + use_extended_packet_size: value + .use_extended_packet_size + .unwrap_or(def.use_extended_packet_size), + use_outfox: value.use_outfox.unwrap_or(def.use_outfox), + } + } +} + +#[derive(Tsify, Debug, Copy, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct CoverTrafficWasmOverride { + /// The parameter of Poisson distribution determining how long, on average, + /// it is going to take for another loop cover traffic message to be sent. + #[tsify(optional)] + pub loop_cover_traffic_average_delay_ms: Option, + + /// Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic. + /// Only applicable if `secondary_packet_size` is enabled. + #[tsify(optional)] + pub cover_traffic_primary_size_ratio: Option, + + /// Controls whether the dedicated loop cover traffic stream should be enabled. + /// (and sending packets, on average, every [Self::loop_cover_traffic_average_delay]) + #[tsify(optional)] + pub disable_loop_cover_traffic_stream: Option, +} + +impl From for CoverTrafficWasm { + fn from(value: CoverTrafficWasmOverride) -> Self { + let def = CoverTrafficWasm::default(); + + CoverTrafficWasm { + loop_cover_traffic_average_delay_ms: value + .loop_cover_traffic_average_delay_ms + .unwrap_or(def.loop_cover_traffic_average_delay_ms), + cover_traffic_primary_size_ratio: value + .cover_traffic_primary_size_ratio + .unwrap_or(def.cover_traffic_primary_size_ratio), + disable_loop_cover_traffic_stream: value + .disable_loop_cover_traffic_stream + .unwrap_or(def.disable_loop_cover_traffic_stream), + } + } +} + +#[derive(Tsify, Debug, Copy, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct GatewayConnectionWasmOverride { + /// How long we're willing to wait for a response to a message sent to the gateway, + /// before giving up on it. + #[tsify(optional)] + pub gateway_response_timeout_ms: Option, +} + +impl From for GatewayConnectionWasm { + fn from(value: GatewayConnectionWasmOverride) -> Self { + let def = GatewayConnectionWasm::default(); + + GatewayConnectionWasm { + gateway_response_timeout_ms: value + .gateway_response_timeout_ms + .unwrap_or(def.gateway_response_timeout_ms), + } + } +} + +#[derive(Tsify, Debug, Copy, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct AcknowledgementsWasmOverride { + /// The parameter of Poisson distribution determining how long, on average, + /// sent acknowledgement is going to be delayed at any given mix node. + /// So for an ack going through three mix nodes, on average, it will take three times this value + /// until the packet reaches its destination. + #[tsify(optional)] + pub average_ack_delay_ms: Option, + + /// Value multiplied with the expected round trip time of an acknowledgement packet before + /// it is assumed it was lost and retransmission of the data packet happens. + /// In an ideal network with 0 latency, this value would have been 1. + #[tsify(optional)] + pub ack_wait_multiplier: Option, + + /// Value added to the expected round trip time of an acknowledgement packet before + /// it is assumed it was lost and retransmission of the data packet happens. + /// In an ideal network with 0 latency, this value would have been 0. + #[tsify(optional)] + pub ack_wait_addition_ms: Option, +} + +impl From for AcknowledgementsWasm { + fn from(value: AcknowledgementsWasmOverride) -> Self { + let def = AcknowledgementsWasm::default(); + + AcknowledgementsWasm { + average_ack_delay_ms: value + .average_ack_delay_ms + .unwrap_or(def.average_ack_delay_ms), + ack_wait_multiplier: value.ack_wait_multiplier.unwrap_or(def.ack_wait_multiplier), + ack_wait_addition_ms: value + .ack_wait_addition_ms + .unwrap_or(def.ack_wait_addition_ms), + } + } +} + +#[derive(Tsify, Debug, Copy, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct TopologyWasmOverride { + /// The uniform delay every which clients are querying the directory server + /// to try to obtain a compatible network topology to send sphinx packets through. + #[tsify(optional)] + pub topology_refresh_rate_ms: Option, + + /// During topology refresh, test packets are sent through every single possible network + /// path. This timeout determines waiting period until it is decided that the packet + /// did not reach its destination. + #[tsify(optional)] + pub topology_resolution_timeout_ms: Option, + + /// Specifies whether the client should not refresh the network topology after obtaining + /// the first valid instance. + /// Supersedes `topology_refresh_rate_ms`. + #[tsify(optional)] + pub disable_refreshing: Option, +} + +impl From for TopologyWasm { + fn from(value: TopologyWasmOverride) -> Self { + let def = TopologyWasm::default(); + + TopologyWasm { + topology_refresh_rate_ms: value + .topology_refresh_rate_ms + .unwrap_or(def.topology_refresh_rate_ms), + topology_resolution_timeout_ms: value + .topology_resolution_timeout_ms + .unwrap_or(def.topology_resolution_timeout_ms), + disable_refreshing: value.disable_refreshing.unwrap_or(def.disable_refreshing), + } + } +} + +#[derive(Tsify, Debug, Copy, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct ReplySurbsWasmOverride { + /// Defines the minimum number of reply surbs the client wants to keep in its storage at all times. + /// It can only allow to go below that value if its to request additional reply surbs. + #[tsify(optional)] + pub minimum_reply_surb_storage_threshold: Option, + + /// Defines the maximum number of reply surbs the client wants to keep in its storage at any times. + #[tsify(optional)] + pub maximum_reply_surb_storage_threshold: Option, + + /// Defines the minimum number of reply surbs the client would request. + #[tsify(optional)] + pub minimum_reply_surb_request_size: Option, + + /// Defines the maximum number of reply surbs the client would request. + #[tsify(optional)] + pub maximum_reply_surb_request_size: Option, + + /// Defines the maximum number of reply surbs a remote party is allowed to request from this client at once. + #[tsify(optional)] + pub maximum_allowed_reply_surb_request_size: Option, + + /// Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking + /// for more even though in theory they wouldn't need to. + #[tsify(optional)] + pub maximum_reply_surb_rerequest_waiting_period_ms: Option, + + /// Defines maximum amount of time the client is going to wait for reply surbs before + /// deciding it's never going to get them and would drop all pending messages + #[tsify(optional)] + pub maximum_reply_surb_drop_waiting_period_ms: Option, + + /// Defines maximum amount of time given reply surb is going to be valid for. + /// This is going to be superseded by key rotation once implemented. + #[tsify(optional)] + pub maximum_reply_surb_age_ms: Option, + + /// Defines maximum amount of time given reply key is going to be valid for. + /// This is going to be superseded by key rotation once implemented. + #[tsify(optional)] + pub maximum_reply_key_age_ms: Option, +} + +impl From for ReplySurbsWasm { + fn from(value: ReplySurbsWasmOverride) -> Self { + let def = ReplySurbsWasm::default(); + + ReplySurbsWasm { + minimum_reply_surb_storage_threshold: value + .minimum_reply_surb_storage_threshold + .unwrap_or(def.minimum_reply_surb_storage_threshold), + maximum_reply_surb_storage_threshold: value + .maximum_reply_surb_storage_threshold + .unwrap_or(def.maximum_reply_surb_storage_threshold), + minimum_reply_surb_request_size: value + .minimum_reply_surb_request_size + .unwrap_or(def.minimum_reply_surb_request_size), + maximum_reply_surb_request_size: value + .maximum_reply_surb_request_size + .unwrap_or(def.maximum_reply_surb_request_size), + maximum_allowed_reply_surb_request_size: value + .maximum_allowed_reply_surb_request_size + .unwrap_or(def.maximum_allowed_reply_surb_request_size), + maximum_reply_surb_rerequest_waiting_period_ms: value + .maximum_reply_surb_rerequest_waiting_period_ms + .unwrap_or(def.maximum_reply_surb_rerequest_waiting_period_ms), + maximum_reply_surb_drop_waiting_period_ms: value + .maximum_reply_surb_drop_waiting_period_ms + .unwrap_or(def.maximum_reply_surb_drop_waiting_period_ms), + maximum_reply_surb_age_ms: value + .maximum_reply_surb_age_ms + .unwrap_or(def.maximum_reply_surb_age_ms), + maximum_reply_key_age_ms: value + .maximum_reply_key_age_ms + .unwrap_or(def.maximum_reply_key_age_ms), + } + } +} diff --git a/clients/webassembly/src/error.rs b/common/wasm/client-core/src/error.rs similarity index 73% rename from clients/webassembly/src/error.rs rename to common/wasm/client-core/src/error.rs index 9cf2369994..01cbbcd757 100644 --- a/clients/webassembly/src/error.rs +++ b/common/wasm/client-core/src/error.rs @@ -1,30 +1,22 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::storage::error::ClientStorageError; +use crate::storage::wasm_client_traits::WasmClientStorageError; use crate::topology::WasmTopologyError; use js_sys::Promise; use nym_client_core::config::GatewayEndpointConfig; use nym_client_core::error::ClientCoreError; use nym_crypto::asymmetric::identity::Ed25519RecoveryError; use nym_gateway_client::error::GatewayClientError; -use nym_node_tester_utils::error::NetworkTestingError; use nym_sphinx::addressing::clients::RecipientFormattingError; use nym_sphinx::anonymous_replies::requests::InvalidAnonymousSenderTagRepresentation; use nym_topology::NymTopologyError; use nym_validator_client::ValidatorClientError; use thiserror::Error; -use wasm_bindgen::JsValue; -use wasm_utils::simple_js_error; +use wasm_utils::wasm_error; -// might as well start using well-defined error enum... #[derive(Debug, Error)] -pub enum WasmClientError { - #[error( - "A node test is already in progress. Wait for it to finish before starting another one." - )] - TestInProgress, - +pub enum WasmCoreError { #[error("experienced an issue with internal client components: {source}")] BaseClientError { #[from] @@ -58,12 +50,6 @@ pub enum WasmClientError { source: NymTopologyError, }, - #[error("failed to test the node: {source}")] - NodeTestingFailure { - #[from] - source: NetworkTestingError, - }, - #[error("{raw} is not a valid url: {source}")] MalformedUrl { raw: String, @@ -92,9 +78,15 @@ pub enum WasmClientError { }, #[error(transparent)] - StorageError { + BaseStorageError { #[from] - source: ClientStorageError, + source: wasm_storage::error::StorageError, + }, + + #[error(transparent)] + ClientStorageError { + #[from] + source: WasmClientStorageError, }, #[error("this client has already registered with a gateway: {gateway_config:?}")] @@ -103,20 +95,4 @@ pub enum WasmClientError { }, } -impl WasmClientError { - pub fn into_rejected_promise(self) -> Promise { - self.into() - } -} - -impl From for JsValue { - fn from(value: WasmClientError) -> Self { - simple_js_error(value.to_string()) - } -} - -impl From for Promise { - fn from(value: WasmClientError) -> Self { - Promise::reject(&value.into()) - } -} +wasm_error!(WasmCoreError); diff --git a/clients/webassembly/src/helpers.rs b/common/wasm/client-core/src/helpers.rs similarity index 72% rename from clients/webassembly/src/helpers.rs rename to common/wasm/client-core/src/helpers.rs index 68831dd19b..e6aacfe2b7 100644 --- a/clients/webassembly/src/helpers.rs +++ b/common/wasm/client-core/src/helpers.rs @@ -1,7 +1,8 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::error::WasmClientError; +use crate::error::WasmCoreError; +use crate::storage::wasm_client_traits::WasmClientStorage; use crate::storage::ClientStorage; use crate::topology::WasmNymTopology; use js_sys::Promise; @@ -18,44 +19,44 @@ use rand::thread_rng; use url::Url; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen_futures::future_to_promise; -use wasm_utils::PromisableResult; +use wasm_utils::error::PromisableResult; + +pub use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage; // don't get too excited about the name, under the hood it's just a big fat placeholder // with no disk_persistence -pub(crate) fn setup_reply_surb_storage_backend( - config: config::ReplySurbs, -) -> browser_backend::Backend { +pub fn setup_reply_surb_storage_backend(config: config::ReplySurbs) -> browser_backend::Backend { browser_backend::Backend::new( config.minimum_reply_surb_storage_threshold, config.maximum_reply_surb_storage_threshold, ) } -pub(crate) fn parse_recipient(recipient: &str) -> Result { +pub fn parse_recipient(recipient: &str) -> Result { Recipient::try_from_base58_string(recipient).map_err(|source| { - WasmClientError::MalformedRecipient { + WasmCoreError::MalformedRecipient { raw: recipient.to_string(), source, } }) } -pub(crate) fn parse_sender_tag(tag: &str) -> Result { +pub fn parse_sender_tag(tag: &str) -> Result { AnonymousSenderTag::try_from_base58_string(tag).map_err(|source| { - WasmClientError::MalformedSenderTag { + WasmCoreError::MalformedSenderTag { raw: tag.to_string(), source, } }) } -pub(crate) async fn current_network_topology_async( +pub async fn current_network_topology_async( nym_api_url: String, -) -> Result { +) -> Result { let url: Url = match nym_api_url.parse() { Ok(url) => url, Err(source) => { - return Err(WasmClientError::MalformedUrl { + return Err(WasmCoreError::MalformedUrl { raw: nym_api_url, source, }) @@ -69,11 +70,13 @@ pub(crate) async fn current_network_topology_async( Ok(NymTopology::from_detailed(mixnodes, gateways).into()) } -#[wasm_bindgen] +#[wasm_bindgen(js_name = "currentNetworkTopology")] pub fn current_network_topology(nym_api_url: String) -> Promise { + // blame js for that serde conversion future_to_promise(async move { current_network_topology_async(nym_api_url) .await + .map(|topology| serde_wasm_bindgen::to_value(&topology).unwrap()) .into_promise_result() }) } @@ -82,7 +85,7 @@ async fn setup_gateway( client_store: &ClientStorage, chosen_gateway: Option, gateways: &[gateway::Node], -) -> Result { +) -> Result { let setup = if client_store.has_full_gateway_info().await? { GatewaySetup::MustLoad } else { @@ -94,21 +97,21 @@ async fn setup_gateway( .map_err(Into::into) } -pub(crate) async fn setup_gateway_from_api( +pub async fn setup_gateway_from_api( client_store: &ClientStorage, chosen_gateway: Option, nym_apis: &[Url], -) -> Result { +) -> Result { let mut rng = thread_rng(); let gateways = current_gateways(&mut rng, nym_apis).await?; setup_gateway(client_store, chosen_gateway, &gateways).await } -pub(crate) async fn setup_from_topology( +pub async fn setup_from_topology( explicit_gateway: Option, topology: &NymTopology, client_store: &ClientStorage, -) -> Result { +) -> Result { let gateways = topology.gateways(); setup_gateway(client_store, explicit_gateway, gateways).await } diff --git a/common/wasm/client-core/src/lib.rs b/common/wasm/client-core/src/lib.rs new file mode 100644 index 0000000000..95ce12ad3c --- /dev/null +++ b/common/wasm/client-core/src/lib.rs @@ -0,0 +1,50 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +#[cfg(target_arch = "wasm32")] +pub mod config; +#[cfg(target_arch = "wasm32")] +pub mod error; +#[cfg(target_arch = "wasm32")] +pub mod helpers; +#[cfg(target_arch = "wasm32")] +pub mod storage; +#[cfg(target_arch = "wasm32")] +pub mod topology; + +// re-export types for ease of use +pub use nym_bandwidth_controller::BandwidthController; +pub use nym_client_core::*; +pub use nym_client_core::{ + client::key_manager::ManagedKeys, + error::ClientCoreError, + init::{InitialisationDetails, InitialisationResult}, +}; +pub use nym_gateway_client::{error::GatewayClientError, GatewayClient}; +pub use nym_sphinx::{ + addressing::{clients::Recipient, nodes::NodeIdentity}, + params::PacketType, + receiver::ReconstructedMessage, +}; +pub use nym_task; +pub use nym_topology::{HardcodedTopologyProvider, MixLayer, NymTopology, TopologyProvider}; +pub use nym_validator_client::nym_api::Client as ApiClient; +pub use nym_validator_client::{DirectSigningReqwestRpcNyxdClient, QueryReqwestRpcNyxdClient}; +// TODO: that's a very nasty import path. it should come from contracts instead! +pub use nym_validator_client::client::IdentityKey; + +#[cfg(target_arch = "wasm32")] +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +#[cfg(target_arch = "wasm32")] +pub fn set_panic_hook() { + // When the `console_error_panic_hook` feature is enabled, we can call the + // `set_panic_hook` function at least once during initialization, and then + // we will get better error messages if our code ever panics. + // + // For more details see + // https://github.com/rustwasm/console_error_panic_hook#readme + #[cfg(feature = "console_error_panic_hook")] + console_error_panic_hook::set_once(); +} diff --git a/clients/webassembly/src/storage/traits.rs b/common/wasm/client-core/src/storage/core_client_traits.rs similarity index 80% rename from clients/webassembly/src/storage/traits.rs rename to common/wasm/client-core/src/storage/core_client_traits.rs index f4a4c35742..0a0114d55c 100644 --- a/clients/webassembly/src/storage/traits.rs +++ b/common/wasm/client-core/src/storage/core_client_traits.rs @@ -1,7 +1,10 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::storage::error::ClientStorageError; +use crate::config::BaseClientConfig; +use crate::error::WasmCoreError; +use crate::helpers::setup_reply_surb_storage_backend; +use crate::storage::wasm_client_traits::WasmClientStorage; use crate::storage::ClientStorage; use async_trait::async_trait; use nym_client_core::client::base_client::storage::gateway_details::{ @@ -22,6 +25,17 @@ pub struct FullWasmClientStorage { pub(crate) credential_storage: EphemeralCredentialStorage, } +impl FullWasmClientStorage { + // TODO: I dont like that base_config type, it should be something wasm-specific. + pub fn new(base_config: &BaseClientConfig, base_storage: ClientStorage) -> Self { + FullWasmClientStorage { + keys_and_gateway_store: base_storage, + reply_storage: setup_reply_surb_storage_backend(base_config.debug.reply_surbs), + credential_storage: EphemeralCredentialStorage::default(), + } + } +} + impl MixnetClientStorage for FullWasmClientStorage { type KeyStore = ClientStorage; type ReplyStore = browser_backend::Backend; @@ -52,7 +66,7 @@ impl MixnetClientStorage for FullWasmClientStorage { #[async_trait(?Send)] impl KeyStore for ClientStorage { - type StorageError = ClientStorageError; + type StorageError = WasmCoreError; async fn load_keys(&self) -> Result { console_log!("attempting to load cryptographic keys..."); @@ -86,7 +100,7 @@ impl KeyStore for ClientStorage { #[async_trait(?Send)] impl GatewayDetailsStore for ClientStorage { - type StorageError = ClientStorageError; + type StorageError = WasmCoreError; async fn load_gateway_details(&self) -> Result { self.must_read_gateway_details().await @@ -96,6 +110,6 @@ impl GatewayDetailsStore for ClientStorage { &self, details: &PersistedGatewayDetails, ) -> Result<(), Self::StorageError> { - self.store_gateway_details(details).await + ::store_gateway_details(self, details).await } } diff --git a/common/wasm/client-core/src/storage/mod.rs b/common/wasm/client-core/src/storage/mod.rs new file mode 100644 index 0000000000..c94e8fc599 --- /dev/null +++ b/common/wasm/client-core/src/storage/mod.rs @@ -0,0 +1,151 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::error::WasmCoreError; +use crate::storage::wasm_client_traits::{v1, WasmClientStorage}; +use async_trait::async_trait; +use js_sys::{Array, Promise}; +use serde::de::DeserializeOwned; +use serde::Serialize; +use wasm_bindgen::prelude::*; +use wasm_bindgen_futures::future_to_promise; +use wasm_storage::traits::BaseWasmStorage; +use wasm_storage::{IdbVersionChangeEvent, WasmStorage}; +use wasm_utils::error::PromisableResult; +use zeroize::Zeroizing; + +pub mod core_client_traits; +pub mod wasm_client_traits; + +const STORAGE_NAME_PREFIX: &str = "wasm-client-storage"; +const STORAGE_VERSION: u32 = 1; + +#[wasm_bindgen] +pub struct ClientStorage { + #[allow(dead_code)] + pub(crate) name: String, + pub(crate) inner: WasmStorage, +} + +#[wasm_bindgen] +impl ClientStorage { + fn db_name(client_id: &str) -> String { + format!("{STORAGE_NAME_PREFIX}-{client_id}") + } + + pub async fn new_async( + client_id: &str, + passphrase: Option, + ) -> Result { + let name = Self::db_name(client_id); + + // make sure the password is zeroized when no longer used, especially if we error out. + // special care must be taken on JS side to ensure it's correctly used there. + let passphrase = Zeroizing::new(passphrase); + + let migrate_fn = Some(|evt: &IdbVersionChangeEvent| -> Result<(), JsValue> { + // Even if the web-sys bindings expose the version as a f64, the IndexedDB API + // works with an unsigned integer. + // See + let old_version = evt.old_version() as u32; + + if old_version < 1 { + // migrating to version 1 + let db = evt.db(); + + db.create_object_store(v1::KEYS_STORE)?; + db.create_object_store(v1::CORE_STORE)?; + } + + Ok(()) + }); + + let inner = WasmStorage::new( + &name, + STORAGE_VERSION, + migrate_fn, + passphrase.as_ref().map(|p| p.as_bytes()), + ) + .await?; + + Ok(ClientStorage { inner, name }) + } + + #[wasm_bindgen(constructor)] + #[allow(clippy::new_ret_no_self)] + pub fn new(client_id: String, passphrase: String) -> Promise { + future_to_promise(async move { + Self::new_async(&client_id, Some(passphrase)) + .await + .into_promise_result() + }) + } + + pub fn new_unencrypted(client_id: String) -> Promise { + future_to_promise(async move { + Self::new_async(&client_id, None) + .await + .into_promise_result() + }) + } +} + +#[async_trait(?Send)] +impl BaseWasmStorage for ClientStorage { + type StorageError = WasmCoreError; + + async fn exists(db_name: &str) -> Result { + Ok(WasmStorage::exists(db_name).await?) + } + + async fn read_value(&self, store: &str, key: K) -> Result, Self::StorageError> + where + T: DeserializeOwned, + K: JsCast, + { + Ok(self.inner.read_value(store, key).await?) + } + + async fn store_value( + &self, + store: &str, + key: K, + value: &T, + ) -> Result<(), Self::StorageError> + where + T: Serialize, + K: JsCast, + { + Ok(self.inner.store_value(store, key, value).await?) + } + + async fn remove_value(&self, store: &str, key: K) -> Result<(), Self::StorageError> + where + K: JsCast, + { + Ok(self.inner.remove_value(store, key).await?) + } + + async fn has_value(&self, store: &str, key: K) -> Result + where + K: JsCast, + { + Ok(self.inner.has_value(store, key).await?) + } + + async fn key_count(&self, store: &str, key: K) -> Result + where + K: JsCast, + { + Ok(self.inner.key_count(store, key).await?) + } + + async fn get_all_keys(&self, store: &str) -> Result { + Ok(self.inner.get_all_keys(store).await?) + } +} + +#[async_trait(?Send)] +impl WasmClientStorage for ClientStorage { + type StorageError = WasmCoreError; +} diff --git a/common/wasm/client-core/src/storage/wasm_client_traits.rs b/common/wasm/client-core/src/storage/wasm_client_traits.rs new file mode 100644 index 0000000000..83e0ca1340 --- /dev/null +++ b/common/wasm/client-core/src/storage/wasm_client_traits.rs @@ -0,0 +1,220 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use async_trait::async_trait; +use nym_client_core::client::base_client::storage::gateway_details::PersistedGatewayDetails; +use nym_crypto::asymmetric::{encryption, identity}; +use nym_gateway_client::SharedKeys; +use nym_sphinx_acknowledgements::AckKey; +use std::error::Error; +use thiserror::Error; +use wasm_bindgen::JsValue; +use wasm_storage::traits::BaseWasmStorage; + +// v1 tables +pub(crate) mod v1 { + // stores + pub const KEYS_STORE: &str = "keys"; + pub const CORE_STORE: &str = "core"; + + // keys + // pub const CONFIG: &str = "config"; + pub const GATEWAY_DETAILS: &str = "gateway_details"; + + pub const ED25519_IDENTITY_KEYPAIR: &str = "ed25519_identity_keypair"; + pub const X25519_ENCRYPTION_KEYPAIR: &str = "x25519_encryption_keypair"; + + // TODO: for those we could actually use the subtle crypto storage + pub const AES128CTR_ACK_KEY: &str = "aes128ctr_ack_key"; + pub const AES128CTR_BLAKE3_HMAC_GATEWAY_KEYS: &str = "aes128ctr_blake3_hmac_gateway_keys"; +} + +#[derive(Debug, Error)] +pub enum WasmClientStorageError { + #[error("{typ} cryptographic key is not available in storage")] + CryptoKeyNotInStorage { typ: String }, + + #[error("the prior gateway details are not available in the storage")] + GatewayDetailsNotInStorage, +} + +#[async_trait(?Send)] +pub trait WasmClientStorage: BaseWasmStorage { + type StorageError: Error + + From<::StorageError> + + From; + + async fn may_read_gateway_details( + &self, + ) -> Result, ::StorageError> { + self.read_value(v1::CORE_STORE, JsValue::from_str(v1::GATEWAY_DETAILS)) + .await + .map_err(Into::into) + } + + async fn must_read_gateway_details( + &self, + ) -> Result::StorageError> { + self.may_read_gateway_details() + .await? + .ok_or(WasmClientStorageError::GatewayDetailsNotInStorage) + .map_err(Into::into) + } + + async fn may_read_identity_keypair( + &self, + ) -> Result, ::StorageError> { + self.read_value( + v1::KEYS_STORE, + JsValue::from_str(v1::ED25519_IDENTITY_KEYPAIR), + ) + .await + .map_err(Into::into) + } + + async fn may_read_encryption_keypair( + &self, + ) -> Result, ::StorageError> { + self.read_value( + v1::KEYS_STORE, + JsValue::from_str(v1::X25519_ENCRYPTION_KEYPAIR), + ) + .await + .map_err(Into::into) + } + + async fn may_read_ack_key( + &self, + ) -> Result, ::StorageError> { + self.read_value(v1::KEYS_STORE, JsValue::from_str(v1::AES128CTR_ACK_KEY)) + .await + .map_err(Into::into) + } + + async fn may_read_gateway_shared_key( + &self, + ) -> Result, ::StorageError> { + self.read_value( + v1::KEYS_STORE, + JsValue::from_str(v1::AES128CTR_BLAKE3_HMAC_GATEWAY_KEYS), + ) + .await + .map_err(Into::into) + } + + async fn must_read_identity_keypair( + &self, + ) -> Result::StorageError> { + self.may_read_identity_keypair() + .await? + .ok_or(WasmClientStorageError::CryptoKeyNotInStorage { + typ: v1::ED25519_IDENTITY_KEYPAIR.to_string(), + }) + .map_err(Into::into) + } + + async fn must_read_encryption_keypair( + &self, + ) -> Result::StorageError> { + self.may_read_encryption_keypair() + .await? + .ok_or(WasmClientStorageError::CryptoKeyNotInStorage { + typ: v1::X25519_ENCRYPTION_KEYPAIR.to_string(), + }) + .map_err(Into::into) + } + + async fn must_read_ack_key(&self) -> Result::StorageError> { + self.may_read_ack_key() + .await? + .ok_or(WasmClientStorageError::CryptoKeyNotInStorage { + typ: v1::AES128CTR_ACK_KEY.to_string(), + }) + .map_err(Into::into) + } + + async fn must_read_gateway_shared_key( + &self, + ) -> Result::StorageError> { + self.may_read_gateway_shared_key() + .await? + .ok_or(WasmClientStorageError::CryptoKeyNotInStorage { + typ: v1::AES128CTR_BLAKE3_HMAC_GATEWAY_KEYS.to_string(), + }) + .map_err(Into::into) + } + + async fn store_identity_keypair( + &self, + keypair: &identity::KeyPair, + ) -> Result<(), ::StorageError> { + self.store_value( + v1::KEYS_STORE, + JsValue::from_str(v1::ED25519_IDENTITY_KEYPAIR), + keypair, + ) + .await + .map_err(Into::into) + } + + async fn store_encryption_keypair( + &self, + keypair: &encryption::KeyPair, + ) -> Result<(), ::StorageError> { + self.store_value( + v1::KEYS_STORE, + JsValue::from_str(v1::X25519_ENCRYPTION_KEYPAIR), + keypair, + ) + .await + .map_err(Into::into) + } + + async fn store_ack_key( + &self, + key: &AckKey, + ) -> Result<(), ::StorageError> { + self.store_value( + v1::KEYS_STORE, + JsValue::from_str(v1::AES128CTR_ACK_KEY), + key, + ) + .await + .map_err(Into::into) + } + + async fn store_gateway_shared_key( + &self, + key: &SharedKeys, + ) -> Result<(), ::StorageError> { + self.store_value( + v1::KEYS_STORE, + JsValue::from_str(v1::AES128CTR_BLAKE3_HMAC_GATEWAY_KEYS), + key, + ) + .await + .map_err(Into::into) + } + + async fn store_gateway_details( + &self, + gateway_endpoint: &PersistedGatewayDetails, + ) -> Result<(), ::StorageError> { + self.store_value( + v1::CORE_STORE, + JsValue::from_str(v1::GATEWAY_DETAILS), + gateway_endpoint, + ) + .await + .map_err(Into::into) + } + + async fn has_full_gateway_info( + &self, + ) -> Result::StorageError> { + let has_keys = self.may_read_gateway_shared_key().await?.is_some(); + let has_details = self.may_read_gateway_details().await?.is_some(); + + Ok(has_keys && has_details) + } +} diff --git a/common/wasm/client-core/src/topology.rs b/common/wasm/client-core/src/topology.rs new file mode 100644 index 0000000000..ab6ee353d3 --- /dev/null +++ b/common/wasm/client-core/src/topology.rs @@ -0,0 +1,251 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use nym_client_core::config::GatewayEndpointConfig; +use nym_config::defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT}; +use nym_crypto::asymmetric::{encryption, identity}; +use nym_topology::gateway::GatewayConversionError; +use nym_topology::mix::{Layer, MixnodeConversionError}; +use nym_topology::{gateway, mix, MixLayer, NymTopology}; +use nym_validator_client::client::IdentityKeyRef; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; +use thiserror::Error; +use tsify::Tsify; +use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; +use wasm_utils::console_log; +use wasm_utils::error::simple_js_error; + +#[derive(Debug, Error)] +pub enum WasmTopologyError { + #[error("got invalid mix layer {value}. Expected 1, 2 or 3.")] + InvalidMixLayer { value: u8 }, + + #[error(transparent)] + GatewayConversion(#[from] GatewayConversionError), + + #[error(transparent)] + MixnodeConversion(#[from] MixnodeConversionError), + + #[error("The provided mixnode map was malformed: {msg}")] + MalformedMixnodeMap { msg: String }, + + #[error("The provided gateway list was malformed: {msg}")] + MalformedGatewayList { msg: String }, +} + +impl From for JsValue { + fn from(value: WasmTopologyError) -> Self { + simple_js_error(value.to_string()) + } +} + +// serde helper, not intended to be used directly +#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct WasmNymTopology { + mixnodes: BTreeMap>, + gateways: Vec, +} + +impl WasmNymTopology { + pub fn print(&self) { + if !self.mixnodes.is_empty() { + console_log!("mixnodes:"); + for (layer, nodes) in &self.mixnodes { + console_log!("\tlayer {layer}:"); + for node in nodes { + // console_log!("\t\t{} - {}", node.mix_id, node.identity_key) + console_log!("\t\t{} - {:?}", node.mix_id, node) + } + } + } else { + console_log!("NO MIXNODES") + } + + if !self.gateways.is_empty() { + console_log!("gateways:"); + for gateway in &self.gateways { + // console_log!("\t{}", gateway.identity_key) + console_log!("\t{:?}", gateway) + } + } else { + console_log!("NO GATEWAYS") + } + } +} + +impl TryFrom for NymTopology { + type Error = WasmTopologyError; + + fn try_from(value: WasmNymTopology) -> Result { + let mut converted_mixes = BTreeMap::new(); + + for (layer, nodes) in value.mixnodes { + let layer_nodes = nodes + .into_iter() + .map(TryInto::try_into) + .collect::>()?; + + converted_mixes.insert(layer, layer_nodes); + } + + let gateways = value + .gateways + .into_iter() + .map(TryInto::try_into) + .collect::>()?; + + Ok(NymTopology::new(converted_mixes, gateways)) + } +} + +impl WasmNymTopology { + pub fn ensure_contains(&self, gateway_config: &GatewayEndpointConfig) -> bool { + self.ensure_contains_gateway_id(&gateway_config.gateway_id) + } + + pub fn ensure_contains_gateway_id(&self, gateway_id: IdentityKeyRef) -> bool { + self.gateways.iter().any(|g| g.identity_key == gateway_id) + } +} + +impl From for WasmNymTopology { + fn from(value: NymTopology) -> Self { + WasmNymTopology { + mixnodes: value + .mixes() + .iter() + .map(|(&l, nodes)| (l, nodes.iter().map(Into::into).collect())) + .collect(), + gateways: value.gateways().iter().map(Into::into).collect(), + } + } +} + +#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct WasmMixNode { + // this is a `MixId` but due to typescript issue, we're using u32 directly. + pub mix_id: u32, + pub owner: String, + pub host: String, + + #[tsify(optional)] + pub mix_port: Option, + pub identity_key: String, + pub sphinx_key: String, + + // this is a `MixLayer` but due to typescript issue, we're using u8 directly. + pub layer: u8, + + #[tsify(optional)] + pub version: Option, +} + +impl TryFrom for mix::Node { + type Error = WasmTopologyError; + + fn try_from(value: WasmMixNode) -> Result { + let host = mix::Node::parse_host(&value.host)?; + + let mix_port = value.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT); + let version = value.version.map(|v| v.as_str().into()).unwrap_or_default(); + + // try to completely resolve the host in the mix situation to avoid doing it every + // single time we want to construct a path + let mix_host = mix::Node::extract_mix_host(&host, mix_port)?; + + Ok(mix::Node { + mix_id: value.mix_id, + owner: value.owner, + host, + mix_host, + identity_key: identity::PublicKey::from_base58_string(&value.identity_key) + .map_err(MixnodeConversionError::from)?, + sphinx_key: encryption::PublicKey::from_base58_string(&value.sphinx_key) + .map_err(MixnodeConversionError::from)?, + layer: Layer::try_from(value.layer) + .map_err(|_| WasmTopologyError::InvalidMixLayer { value: value.layer })?, + version, + }) + } +} + +impl<'a> From<&'a mix::Node> for WasmMixNode { + fn from(value: &'a mix::Node) -> Self { + WasmMixNode { + mix_id: value.mix_id, + owner: value.owner.clone(), + host: value.host.to_string(), + mix_port: Some(value.mix_host.port()), + identity_key: value.identity_key.to_base58_string(), + sphinx_key: value.sphinx_key.to_base58_string(), + layer: value.layer.into(), + version: Some(value.version.to_string()), + } + } +} + +#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct WasmGateway { + pub owner: String, + pub host: String, + + #[tsify(optional)] + pub mix_port: Option, + + #[tsify(optional)] + pub clients_port: Option, + pub identity_key: String, + pub sphinx_key: String, + + #[tsify(optional)] + pub version: Option, +} + +impl TryFrom for gateway::Node { + type Error = WasmTopologyError; + + fn try_from(value: WasmGateway) -> Result { + let host = gateway::Node::parse_host(&value.host)?; + + let mix_port = value.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT); + let clients_port = value.clients_port.unwrap_or(DEFAULT_CLIENT_LISTENING_PORT); + let version = value.version.map(|v| v.as_str().into()).unwrap_or_default(); + + // try to completely resolve the host in the mix situation to avoid doing it every + // single time we want to construct a path + let mix_host = gateway::Node::extract_mix_host(&host, mix_port)?; + + Ok(gateway::Node { + owner: value.owner, + host, + mix_host, + clients_port, + identity_key: identity::PublicKey::from_base58_string(&value.identity_key) + .map_err(GatewayConversionError::from)?, + sphinx_key: encryption::PublicKey::from_base58_string(&value.sphinx_key) + .map_err(GatewayConversionError::from)?, + version, + }) + } +} + +impl<'a> From<&'a gateway::Node> for WasmGateway { + fn from(value: &'a gateway::Node) -> Self { + WasmGateway { + owner: value.owner.clone(), + host: value.host.to_string(), + mix_port: Some(value.mix_host.port()), + clients_port: Some(value.clients_port), + identity_key: value.identity_key.to_base58_string(), + sphinx_key: value.sphinx_key.to_base58_string(), + version: Some(value.version.to_string()), + } + } +} diff --git a/common/wasm/storage/Cargo.toml b/common/wasm/storage/Cargo.toml new file mode 100644 index 0000000000..35681dbf9e --- /dev/null +++ b/common/wasm/storage/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "wasm-storage" +version = "0.1.0" +authors = ["Jedrzej Stuczynski "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-trait = { workspace = true } +futures = { workspace = true } +js-sys = { workspace = true } +wasm-bindgen = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde-wasm-bindgen = { workspace = true } +indexed_db_futures = { version = " 0.3.0"} +thiserror = { workspace = true } + +nym-store-cipher = { path = "../../store-cipher", features = ["json"] } +wasm-utils = { path = "../utils", default-features = false } \ No newline at end of file diff --git a/common/wasm-utils/src/storage/cipher_export.rs b/common/wasm/storage/src/cipher_export.rs similarity index 100% rename from common/wasm-utils/src/storage/cipher_export.rs rename to common/wasm/storage/src/cipher_export.rs diff --git a/common/wasm-utils/src/storage/error.rs b/common/wasm/storage/src/error.rs similarity index 97% rename from common/wasm-utils/src/storage/error.rs rename to common/wasm/storage/src/error.rs index 9ead907c08..e4da9497f1 100644 --- a/common/wasm-utils/src/storage/error.rs +++ b/common/wasm/storage/src/error.rs @@ -1,11 +1,11 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::simple_js_error; use indexed_db_futures::web_sys::DomException; use serde_wasm_bindgen::Error; use thiserror::Error; use wasm_bindgen::JsValue; +use wasm_utils::error::simple_js_error; #[derive(Debug, Error)] pub enum StorageError { diff --git a/common/wasm-utils/src/storage/mod.rs b/common/wasm/storage/src/lib.rs similarity index 96% rename from common/wasm-utils/src/storage/mod.rs rename to common/wasm/storage/src/lib.rs index eb17949849..434125155d 100644 --- a/common/wasm-utils/src/storage/mod.rs +++ b/common/wasm/storage/src/lib.rs @@ -1,22 +1,23 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::console_log; -use crate::storage::cipher_export::StoredExportedStoreCipher; -use crate::storage::error::StorageError; -use futures::TryFutureExt; +use crate::cipher_export::StoredExportedStoreCipher; +use crate::error::StorageError; use nym_store_cipher::{ Aes256Gcm, Algorithm, EncryptedData, KdfInfo, KeySizeUser, Params, StoreCipher, Unsigned, Version, }; use serde::de::DeserializeOwned; use serde::Serialize; +use std::future::IntoFuture; use wasm_bindgen::JsValue; +use wasm_utils::console_log; pub use indexed_db_futures::prelude::*; mod cipher_export; pub mod error; +pub mod traits; pub const CIPHER_INFO_STORE: &str = "_cipher_store"; pub const CIPHER_STORE_EXPORT: &str = "cipher_store_export_info"; @@ -87,6 +88,16 @@ impl WasmStorage { }) } + pub async fn delete(self) -> Result<(), StorageError> { + self.inner.0.delete()?.into_future().await?; + Ok(()) + } + + pub async fn remove(db_name: &str) -> Result<(), StorageError> { + IdbDatabase::delete_by_name(db_name)?.into_future().await?; + Ok(()) + } + pub async fn exists(db_name: &str) -> Result { let db_req: OpenDbRequest = IdbDatabase::open(db_name)?; let db: IdbDatabase = db_req.into_future().await?; diff --git a/common/wasm/storage/src/traits.rs b/common/wasm/storage/src/traits.rs new file mode 100644 index 0000000000..b9c124fe07 --- /dev/null +++ b/common/wasm/storage/src/traits.rs @@ -0,0 +1,100 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::WasmStorage; +use async_trait::async_trait; +use js_sys::Array; +use serde::de::DeserializeOwned; +use serde::Serialize; +use std::error::Error; + +#[async_trait(?Send)] +pub trait BaseWasmStorage { + type StorageError: Error; + + async fn exists(db_name: &str) -> Result; + + async fn read_value(&self, store: &str, key: K) -> Result, Self::StorageError> + where + T: DeserializeOwned, + K: wasm_bindgen::JsCast; + + async fn store_value( + &self, + store: &str, + key: K, + value: &T, + ) -> Result<(), Self::StorageError> + where + T: Serialize, + K: wasm_bindgen::JsCast; + + async fn remove_value(&self, store: &str, key: K) -> Result<(), Self::StorageError> + where + K: wasm_bindgen::JsCast; + + async fn has_value(&self, store: &str, key: K) -> Result + where + K: wasm_bindgen::JsCast; + + async fn key_count(&self, store: &str, key: K) -> Result + where + K: wasm_bindgen::JsCast; + + async fn get_all_keys(&self, store: &str) -> Result; +} + +#[async_trait(?Send)] +impl BaseWasmStorage for WasmStorage { + type StorageError = crate::error::StorageError; + + async fn exists(db_name: &str) -> Result { + WasmStorage::exists(db_name).await + } + + async fn read_value(&self, store: &str, key: K) -> Result, Self::StorageError> + where + T: DeserializeOwned, + K: wasm_bindgen::JsCast, + { + self.read_value(store, key).await + } + + async fn store_value( + &self, + store: &str, + key: K, + value: &T, + ) -> Result<(), Self::StorageError> + where + T: Serialize, + K: wasm_bindgen::JsCast, + { + self.store_value(store, key, value).await + } + + async fn remove_value(&self, store: &str, key: K) -> Result<(), Self::StorageError> + where + K: wasm_bindgen::JsCast, + { + self.remove_value(store, key).await + } + + async fn has_value(&self, store: &str, key: K) -> Result + where + K: wasm_bindgen::JsCast, + { + self.has_value(store, key).await + } + + async fn key_count(&self, store: &str, key: K) -> Result + where + K: wasm_bindgen::JsCast, + { + self.key_count(store, key).await + } + + async fn get_all_keys(&self, store: &str) -> Result { + self.get_all_keys(store).await + } +} diff --git a/common/wasm/utils/Cargo.toml b/common/wasm/utils/Cargo.toml new file mode 100644 index 0000000000..ac4d1da56a --- /dev/null +++ b/common/wasm/utils/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "wasm-utils" +version = "0.1.0" +authors = ["Jedrzej Stuczynski "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +futures = { workspace = true } +js-sys = { workspace = true } +wasm-bindgen = { workspace = true } +wasm-bindgen-futures = { workspace = true } +getrandom = { workspace = true, features=["js"], optional = true } +gloo-utils = { workspace = true } +gloo-net = { version = "0.3.1", features = ["websocket"], optional = true } +#gloo-net = { path = "../../../../gloo/crates/net", features = ["websocket"], optional = true } + +# we don't want entire tokio-tungstenite, tungstenite itself is just fine - we just want message and error enums +[dependencies.tungstenite] +version = "0.13" +default-features = false +optional = true + +[dependencies.web-sys] +workspace = true +optional = true + +[features] +default = ["sleep"] +sleep = ["web-sys", "web-sys/Window"] +websocket = [ + "getrandom", + "tungstenite", + "gloo-net" +] +crypto = [ + "web-sys", + "web-sys/Crypto", + "web-sys/CryptoKey", + "web-sys/CryptoKeyPair", + "web-sys/SubtleCrypto", + "web-sys/Window", + "web-sys/WorkerGlobalScope", +] diff --git a/common/wasm-utils/src/crypto/asymmetric.rs b/common/wasm/utils/src/crypto/asymmetric.rs similarity index 100% rename from common/wasm-utils/src/crypto/asymmetric.rs rename to common/wasm/utils/src/crypto/asymmetric.rs diff --git a/common/wasm-utils/src/crypto/mod.rs b/common/wasm/utils/src/crypto/mod.rs similarity index 100% rename from common/wasm-utils/src/crypto/mod.rs rename to common/wasm/utils/src/crypto/mod.rs diff --git a/common/wasm-utils/src/crypto/symmetric.rs b/common/wasm/utils/src/crypto/symmetric.rs similarity index 100% rename from common/wasm-utils/src/crypto/symmetric.rs rename to common/wasm/utils/src/crypto/symmetric.rs diff --git a/common/wasm-utils/src/lib.rs b/common/wasm/utils/src/error.rs similarity index 54% rename from common/wasm-utils/src/lib.rs rename to common/wasm/utils/src/error.rs index e0e3804eaa..4d1e1860e2 100644 --- a/common/wasm-utils/src/lib.rs +++ b/common/wasm/utils/src/error.rs @@ -1,58 +1,36 @@ -// Copyright 2021 - Nym Technologies SA +// Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use wasm_bindgen::prelude::*; +use js_sys::Promise; use wasm_bindgen::JsValue; -#[cfg(feature = "websocket")] -pub mod websocket; - -#[cfg(feature = "crypto")] -pub mod crypto; - -#[cfg(feature = "storage")] -pub mod storage; - -// will cause messages to be written as if console.log("...") was called #[macro_export] -macro_rules! console_log { - ($($t:tt)*) => ($crate::log(&format_args!($($t)*).to_string())) +macro_rules! wasm_error { + ($struct:ident) => { + impl $struct { + pub fn into_rejected_promise(self) -> js_sys::Promise { + self.into() + } + } + + impl From<$struct> for wasm_bindgen::JsValue { + fn from(value: $struct) -> Self { + $crate::error::simple_js_error(value.to_string()) + } + } + + impl From<$struct> for js_sys::Promise { + fn from(value: $struct) -> Self { + Promise::reject(&value.into()) + } + } + }; } -// will cause messages to be written as if console.warn("...") was called -#[macro_export] -macro_rules! console_warn { - ($($t:tt)*) => ($crate::warn(&format_args!($($t)*).to_string())) -} - -// will cause messages to be written as if console.error("...") was called -#[macro_export] -macro_rules! console_error { - ($($t:tt)*) => ($crate::error(&format_args!($($t)*).to_string())) -} - -#[wasm_bindgen] -extern "C" { - #[wasm_bindgen(js_namespace = console)] - pub fn log(s: &str); - - #[wasm_bindgen(js_namespace = console)] - pub fn warn(s: &str); - - #[wasm_bindgen(js_namespace = console)] - pub fn error(s: &str); -} - -#[cfg(feature = "sleep")] -pub async fn sleep(ms: i32) -> Result<(), JsValue> { - let promise = js_sys::Promise::new(&mut |yes, _| { - let win = web_sys::window().expect("no window available!"); - win.set_timeout_with_callback_and_timeout_and_arguments_0(&yes, ms) - .unwrap(); - }); - let js_fut = wasm_bindgen_futures::JsFuture::from(promise); - js_fut.await?; - Ok(()) +/// A helper that constructs a `Promise` containing a wrapper JS error. +pub fn simple_rejected_promise>(err_message: S) -> Promise { + let err = simple_js_error(err_message); + Promise::reject(&err) } /// A helper that construct a `JsValue` containing an error with the provided message. @@ -121,7 +99,7 @@ where #[macro_export] macro_rules! check_promise_result { ( $x:expr ) => { - match $crate::PromisableResultError::map_promise_err($x) { + match $crate::error::PromisableResultError::map_promise_err($x) { Ok(r) => r, Err(err) => return js_sys::Promise::reject(&err), } diff --git a/common/wasm/utils/src/lib.rs b/common/wasm/utils/src/lib.rs new file mode 100644 index 0000000000..1781771067 --- /dev/null +++ b/common/wasm/utils/src/lib.rs @@ -0,0 +1,72 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use wasm_bindgen::prelude::*; + +#[cfg(feature = "websocket")] +pub mod websocket; + +#[cfg(feature = "crypto")] +pub mod crypto; + +pub mod error; + +// will cause messages to be written as if console.log("...") was called +#[macro_export] +macro_rules! console_log { + ($($t:tt)*) => ($crate::log(&format_args!($($t)*).to_string())) +} + +// will cause messages to be written as if console.debug("...") was called +#[macro_export] +macro_rules! console_debug { + ($($t:tt)*) => ($crate::debug(&format_args!($($t)*).to_string())) +} + +// will cause messages to be written as if console.info("...") was called +#[macro_export] +macro_rules! console_info { + ($($t:tt)*) => ($crate::info(&format_args!($($t)*).to_string())) +} + +// will cause messages to be written as if console.warn("...") was called +#[macro_export] +macro_rules! console_warn { + ($($t:tt)*) => ($crate::warn(&format_args!($($t)*).to_string())) +} + +// will cause messages to be written as if console.error("...") was called +#[macro_export] +macro_rules! console_error { + ($($t:tt)*) => ($crate::error(&format_args!($($t)*).to_string())) +} + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_namespace = console)] + pub fn log(s: &str); + + #[wasm_bindgen(js_namespace = console)] + pub fn debug(s: &str); + + #[wasm_bindgen(js_namespace = console)] + pub fn info(s: &str); + + #[wasm_bindgen(js_namespace = console)] + pub fn warn(s: &str); + + #[wasm_bindgen(js_namespace = console)] + pub fn error(s: &str); +} + +#[cfg(feature = "sleep")] +pub async fn sleep(ms: i32) -> Result<(), wasm_bindgen::JsValue> { + let promise = js_sys::Promise::new(&mut |yes, _| { + let win = web_sys::window().expect("no window available!"); + win.set_timeout_with_callback_and_timeout_and_arguments_0(&yes, ms) + .unwrap(); + }); + let js_fut = wasm_bindgen_futures::JsFuture::from(promise); + js_fut.await?; + Ok(()) +} diff --git a/common/wasm/utils/src/websocket/mod.rs b/common/wasm/utils/src/websocket/mod.rs new file mode 100644 index 0000000000..5978f0940d --- /dev/null +++ b/common/wasm/utils/src/websocket/mod.rs @@ -0,0 +1,108 @@ +// Copyright 2021-2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::console_log; +use futures::{Sink, Stream}; +use gloo_net::websocket::futures::WebSocket; +use gloo_net::websocket::{Message, WebSocketError}; +use gloo_utils::errors::JsError; +use std::io; +use std::pin::Pin; +use std::task::{Context, Poll}; +use tungstenite::{Error as WsError, Message as WsMessage}; // use tungstenite Message and Error types for easier compatibility with `ClientHandshake` + +// Unfortunately this can't be cleanly done with TryFrom/TryInto traits as both are foreign types +fn into_tungstenite_message(msg: gloo_net::websocket::Message) -> WsMessage { + match msg { + Message::Text(text) => WsMessage::Text(text), + Message::Bytes(bytes) => WsMessage::Binary(bytes), + } +} + +fn map_ws_error(err: WebSocketError) -> WsError { + match err { + // TODO: are we preserving correct semantics? + WebSocketError::ConnectionError => WsError::ConnectionClosed, + WebSocketError::ConnectionClose(_event) => WsError::ConnectionClosed, + WebSocketError::MessageSendError(err) => { + WsError::Io(io::Error::new(io::ErrorKind::Other, err.to_string())) + } + _ => WsError::Io(io::Error::new(io::ErrorKind::Other, "new websocket error")), + } +} + +fn try_from_tungstenite_message(msg: WsMessage) -> Result { + match msg { + WsMessage::Text(text) => Ok(gloo_net::websocket::Message::Text(text)), + WsMessage::Binary(bytes) => Ok(gloo_net::websocket::Message::Bytes(bytes)), + _ => Err(WsError::Io(io::Error::from(io::ErrorKind::InvalidInput))), + } +} + +// Safety: when compiled to wasm32 everything is going to be running on a single thread and so there +// is no shared memory right now. +// +// ************************************ +// SUPER IMPORTANT TODO: ONCE WASM IN RUST MATURES AND BECOMES MULTI-THREADED THIS MIGHT +// LEAD TO RUNTIME MEMORY CORRUPTION!! +// ************************************ +// +// note: https://github.com/rustwasm/gloo/issues/109 +unsafe impl Send for JSWebsocket {} + +#[allow(clippy::upper_case_acronyms)] +pub struct JSWebsocket { + inner: WebSocket, +} + +impl JSWebsocket { + pub fn new(url: &str) -> Result { + let inner = WebSocket::open(url)?; + console_log!("Websocket to {:?} is now open!", url); + Ok(JSWebsocket { inner }) + } + + pub async fn close(self, code: Option, reason: Option<&str>) -> Result<(), JsError> { + self.inner.close(code, reason) + } +} + +impl Stream for JSWebsocket { + type Item = Result; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.inner).poll_next(cx).map(|maybe_item| { + maybe_item.map(|item| item.map(into_tungstenite_message).map_err(map_ws_error)) + }) + } +} + +impl Sink for JSWebsocket { + type Error = WsError; + + fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.inner) + .poll_ready(cx) + .map(|ready_res| ready_res.map_err(map_ws_error)) + } + + fn start_send(mut self: Pin<&mut Self>, item: WsMessage) -> Result<(), Self::Error> { + let item = try_from_tungstenite_message(item)?; + + Pin::new(&mut self.inner) + .start_send(item) + .map_err(map_ws_error) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.inner) + .poll_flush(cx) + .map(|flush_res| flush_res.map_err(map_ws_error)) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.inner) + .poll_close(cx) + .map(|close_res| close_res.map_err(map_ws_error)) + } +} diff --git a/documentation/dev-portal/src/SUMMARY.md b/documentation/dev-portal/src/SUMMARY.md index 2095d6bc30..dcd96a9eef 100644 --- a/documentation/dev-portal/src/SUMMARY.md +++ b/documentation/dev-portal/src/SUMMARY.md @@ -1,6 +1,6 @@ # Summary -[Introduction](introduction.md) +- [Introduction](introduction.md) # Infrastructure @@ -25,7 +25,6 @@ # Integrations - [Integration Options](integrations/integration-options.md) -- [Integration FAQ](integrations/faq.md) - [Mixnet Integration](integrations/mixnet-integration.md) - [Payment Integration](integrations/payment-integration.md) @@ -51,12 +50,17 @@ - [Sending a Message Through the Mixnet](tutorials/simple-service-provider/sending-message.md) +# FAQ + +- [General](faq/general-faq.md) +- [Integrations](faq/integrations-faq.md) +- [Rewards & Token](faq/rewards-faq.md) + # Community Resources - [Nym DevRel AMAs](community-resources/ama.md) - [Community Applications and Guides](community-resources/community-applications-and-guides.md) - [Change Service Grantee Information](info-request.md) -- [Rewards FAQ](community-resources/rewards-faq.md) --- # Misc. diff --git a/documentation/dev-portal/src/faq/general-faq.md b/documentation/dev-portal/src/faq/general-faq.md new file mode 100644 index 0000000000..a6192b2d1d --- /dev/null +++ b/documentation/dev-portal/src/faq/general-faq.md @@ -0,0 +1,45 @@ +# Nym General FAQ + +> If you have questions which are not answered below, please share them at our [DevRel AMAs](../community-resources/ama.md) or seek support in [Nym's community](https://nymtech.net/community) + +### What is Nym? + +Nym is a privacy platform that secures user data and protects against surveillance at the network level. + +The platform does so by leveraging different technological components: + +- **Nym Mixnet**, a type of overlay network that makes both content and metadata of transactions private through mixing, network-level obfuscation and incentivisation (using Sphinx); +- A blockchain called **Nyx**, our Cosmos SDK blockchain, to allow for us to use payment tokens in the form of NYM, as well as smart contracts, in order to create a robust, decentralized, and secure environment incentives for the Mixnet; +- **Coconut**, a zero-knowledge signature scheme, that creates an application-level private access control layer to power Zk-Nyms; +- A utility token **NYM**, to pay for usage, measure reputation and serve as rewards for the privacy infrastructure. + +Simply put, the [Nym network ("Nym")](https://www.feat-nym-update-nym-web.websites.dev.nymte.ch/nym-whitepaper.pdf) is a decentralized and incentivized infrastructure to provision privacy to a broad range of message-based applications and services. Think of it as a [*"Layer 0" privacy infrastructure*](https://blog.nymtech.net/nym-layer-0-privacy-infrastructure-for-the-whole-internet-e53238f9b8e7) for the entire internet. + +**Related articles:** +- [*Nym is not a blockchain, but is powered by one*](https://blog.nymtech.net/nym-is-not-a-blockchain-but-it-is-powered-by-one-4bb16ef16587) +- [*Nym tokens*](https://blog.nymtech.net/nym-tokens-where-do-they-live-and-how-are-they-distributed-cross-chain-8d134bf9c41f) +- [*A breakdown of the smart contracts that run the Nym token economics*](https://blog.nymtech.net/a-breakdown-of-the-smart-contracts-that-run-the-nym-token-economics-3a61b4139f95) +- [*Zk-Nyms are here*](https://blog.nymtech.net/a-breakdown-of-the-smart-contracts-that-run-the-nym-token-economics-3a61b4139f95) +- [*Sphinx: the anonymous data format that powers Nym*](https://blog.nymtech.net/sphinx-tl-dr-the-data-packet-that-can-anonymize-bitcoin-and-the-internet-18d152c6e4dc) + + +### What's the difference between Nym and VPNs? + +Nym is not an onion routing system, it is not a decentralized VPN - it’s much more than that. Nym is a mixnet meant to stop precisely the traffic analysis attacks that Tor and dVPNs are vulnerable to. + +It is an orthogonal design that maintains better privacy and can support anonymity, although usually with a cost in terms of latency. +It basically is an infrastructure on which privacy preserving apps can be built, leveraging the Mixnet and Coconut credentials, amongst others. +The **Nym mixnet and VPNs differ** because VPNs do not mix nor do they protect metadata from an adversary who may be able to watch the entire network. + +**Related articles:** +- [*VPNs, Tor, I2P, how does Nym compare? *](https://blog.nymtech.net/vpns-tor-i2p-how-does-nym-compare-8576824617b8) + + +### What is Nym’s VPN? + +Since Q2 2023 the Nym core team has been working on launching the **first major consumer facing product** that runs on top of the Nym mixnet: a high speed, trustless and decentralized VPN, paid for via the NYM token - facilitating anonymous payments if wished. +The product positions itself as a full-network protection service available across all of a user’s devices, **leveraging the Nym Mixnet** and other primitives to offer split tunneling and traffic obfuscation techniques to protect against censorship. + +**Related articles:** +- [*What does it take to build the most powerful VPN?*](https://blog.nymtech.net/what-does-it-take-to-build-the-worlds-most-powerful-vpn-d351a76ec4e6) + diff --git a/documentation/dev-portal/src/community-resources/rewards-faq.md b/documentation/dev-portal/src/faq/rewards-faq.md similarity index 99% rename from documentation/dev-portal/src/community-resources/rewards-faq.md rename to documentation/dev-portal/src/faq/rewards-faq.md index 78cd37be84..5e16571066 100644 --- a/documentation/dev-portal/src/community-resources/rewards-faq.md +++ b/documentation/dev-portal/src/faq/rewards-faq.md @@ -1,4 +1,4 @@ -## Rewards FAQ +# Rewards FAQ On this page you will find important information about participation in community activities which involve NYM token rewards, such as contests, giveaways, and promotions. Before participating in any such activity, make sure to read this page carefully. diff --git a/documentation/dev-portal/src/glossary.md b/documentation/dev-portal/src/glossary.md index 8c12e1afdc..2e969c84b0 100644 --- a/documentation/dev-portal/src/glossary.md +++ b/documentation/dev-portal/src/glossary.md @@ -5,7 +5,7 @@ __Familiarise yourself with Nym's specific terms and jargon through our glossary ## A **[Address](https://nymtech.net/docs/stable/integrations/addresses-in-nym/)** - A unique string of characters generated from a client keypair. Used to identify clients in the mixnet. -**[Ack](https://nymtech.net/docs/stable/architecture/traffic-flow/#acks)** - Short for "acknowledgement". Whenever a hop is completed, the recieving node will send back an 'ack', so that the sending node knows that the packet was recieved. +**[Ack](https://nymtech.net/docs/architecture/traffic-flow.html#acks--package-retransmission)** - Short for "acknowledgement". Whenever a hop is completed, the recieving node will send back an 'ack', so that the sending node knows that the packet was recieved. **Attacker** - A person or entity who attempts to gain unauthorised access to a computer system, network, or other information resource. @@ -46,7 +46,7 @@ __Familiarise yourself with Nym's specific terms and jargon through our glossary ## M **[Metadata](https://www.opendatasoft.com/en/blog/what-is-metadata-and-why-is-it-important-data)** - A set of data that describes and gives information about other data such as IP addresses, device types, geolocations etc. -**[Mixnet](https://nymtech.net/docs/stable/architecture/traffic-flow/)** - A routing protocol which encrypts and mixes Sphinx packet traffic so that it cannot be determined who is communicating with whom. +**[Mixnet](https://nymtech.net/docs/architecture/traffic-flow.html#mixnet-traffic-flow-1)** - A routing protocol which encrypts and mixes Sphinx packet traffic so that it cannot be determined who is communicating with whom. **[Mix Nodes](https://blog.nymtech.net/nym-mixnodes-deep-dive-d2b91917f097)** - The backbone of the Nym infrastructure, that are organised in a three-layer network referred to as the mixnet that network traffic passes through. It mixes, hides and reorders traffic and are rewarded in NYM tokens for their quality of service. @@ -87,7 +87,7 @@ __Familiarise yourself with Nym's specific terms and jargon through our glossary **[Service Provider](https://nymtech.net/docs/stable/tutorials/nym-simple-websocket-tutorial/)** - Any type of app that can communicate with the mixnet via a Nym Client. -**[SURBs](https://nymtech.net/docs/stable/architecture/traffic-flow)** - Stands for 'Single Use Reply Blocks'. They are a type of crytographic construct used to facilitate secure communication between parties and are designed to allow a sender to send a message to a recipient in sucha a way that the message can only be read by the intended recipient, and cannot be read by anyone else. +**[SURBs](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs)** - Stands for 'Single Use Reply Blocks'. They are a type of crytographic construct used to facilitate secure communication between parties and are designed to allow a sender to send a message to a recipient in sucha a way that the message can only be read by the intended recipient, and cannot be read by anyone else. **Sybil** - In the context of computer networks, a Sybil attach is a type of security attack in which an attacker creates multiple fake identities or "sybils" and uses them to manipulate a network thus gaining control of a network by overwhelming it. @@ -103,4 +103,4 @@ __Familiarise yourself with Nym's specific terms and jargon through our glossary **Websocket** - A computer communications protocol that provides a full-duplex channel over a single TCP connection. It is designed to be used as a base for real-time, two-way communication between a client and a server over the web. ## Z -**Zero Knowledge Proofs** - Cryptographic techniques that make it possible to prove something to be true without having to reveal the evidence. \ No newline at end of file +**Zero Knowledge Proofs** - Cryptographic techniques that make it possible to prove something to be true without having to reveal the evidence. diff --git a/documentation/dev-portal/src/infrastructure/node-types.md b/documentation/dev-portal/src/infrastructure/node-types.md index 589b9ca576..e864208cd3 100644 --- a/documentation/dev-portal/src/infrastructure/node-types.md +++ b/documentation/dev-portal/src/infrastructure/node-types.md @@ -43,4 +43,4 @@ Maybe you would like to concentrate on building a application that uses the mixn Or perhaps you a developer that would like to run a infrastructure node such as a Gateway, Mix node or Network Requestor: * Check out the [Network Overview](https://nymtech.net/docs/architecture/network-overview.html) docs page. -* Take a look at our [Node Setup Guide](https://nymtech.net/docs/nodes/setup-guides.html) with our Nym Docs, containing setup guides for setting up you own infrastructure node. +* Take a look at our [Node Setup Guide](https://nymtech.net/operators/nodes/setup-guides.html) with our Nym Docs, containing setup guides for setting up you own infrastructure node. diff --git a/documentation/dev-portal/src/infrastructure/nym-vs-others.md b/documentation/dev-portal/src/infrastructure/nym-vs-others.md index a9c8f22290..27ec3a4f86 100644 --- a/documentation/dev-portal/src/infrastructure/nym-vs-others.md +++ b/documentation/dev-portal/src/infrastructure/nym-vs-others.md @@ -6,7 +6,7 @@ Nym is the first system we're aware of which provides integrated protection on b The diagram and brief explainer texts below give a high level overview of the difference between Nym and other comparable systems. -> If you want to dig more deeply into the way traffic is packetised and moved through the mixnet, check out the [Mixnet Traffic Flow](https://nymtech.net/docs/stable/architecture/traffic-flow) page of the docs. +> If you want to dig more deeply into the way traffic is packetised and moved through the mixnet, check out the [Mixnet Traffic Flow](https://nymtech.net/docs/architecture/traffic-flow.html) page of the docs. diff --git a/documentation/dev-portal/src/infrastructure/nym.md b/documentation/dev-portal/src/infrastructure/nym.md index 3d32e2a43f..53bc4b377f 100644 --- a/documentation/dev-portal/src/infrastructure/nym.md +++ b/documentation/dev-portal/src/infrastructure/nym.md @@ -1,30 +1,33 @@ # What is Nym? - Nym is a privacy platform that secures user data and protects against surveillance. It leverages the [mixnet](./node-types.md), a type of overlay network that makes both content and metadata of transactions private through network-level obfuscation and incentivisation, and [Coconut](https://nymtech.net/docs/coconut.html), a privacy technology that creates an application-level private access control layer. Nym also utilises [Nyx](https://blog.nymtech.net/nym-now-supports-smart-contracts-2186da46bc7f), our Cosmos SDK blockchain, to allow for us to use payment tokens in the form of `NYM`, as well as smart contracts, in order to create a robust, decentralised, and secure environment for the mixnet. In a nutshell, Nym is a solution that provides strong privacy protection for users in the digital world. +Nym is a privacy platform that secures user data and protects against surveillance. It leverages the [mixnet](./node-types.md), a type of overlay network that makes both content and metadata of transactions private through network-level obfuscation and incentivisation, and [Coconut](https://nymtech.net/docs/coconut.html), a privacy technology that creates an application-level private access control layer. Nym also utilises [Nyx](https://blog.nymtech.net/nym-now-supports-smart-contracts-2186da46bc7f), our Cosmos SDK blockchain, to allow for us to use payment tokens in the form of `NYM`, as well as smart contracts, in order to create a robust, decentralised, and secure environment for the mixnet. In a nutshell, Nym is a solution that provides strong privacy protection for users in the digital world. - ### An overlay network for network-level traffic privacy - Our mixnet design is based on the [Loopix Anonymity System](https://arxiv.org/abs/1703.00536), somewhat modified to provide better quality of service guarantees. +> All the technical nuances about Nym platform can come out quite complex at first. Look for any questions in the [FAQ section](../faq/general-faq.md), take part in our [DevRel AMAs](../community-resources/ama.md) or seek support in [Nym's community](https://nymtech.net/community) - In this brief video, our Head of Research and creator of the Loopix mixnet paper, Ania Piotrowska, delves into the design of the Loopix mixnet in depth at USENix 2017. +### An overlay network for network-level traffic privacy +Our mixnet design is based on the [Loopix Anonymity System](https://arxiv.org/abs/1703.00536), somewhat modified to provide better quality of service guarantees. - +In this brief video, our Head of Research and creator of the Loopix mixnet paper, Ania Piotrowska, delves into the design of the Loopix mixnet in depth at USENix 2017. - The Nym mixnet effectively addresses privacy concerns by utilizing network nodes to mix messages, making them unidentifiable to adversaries. Each packet is layer encrypted, and binary-padded so that it's indistinguishable from all other packets. Incoming packets are "mixed" with all other messages inside the node. That is, the node strips one layer of packet encryption, and adds a small random transmission delay, so that messages are not emitted in the same order as which they arrived. - Next, the message is sent to another mix node, decrypted and mixed again, then to a third mixnode for further mixing. Finally, the message is delivered to its destination gateway. + - As long as there's enough traffic flowing through the nodes, even an adversary who can monitor the entire network cannot trace the packet flow through the system. +The Nym mixnet effectively addresses privacy concerns by utilizing network nodes to mix messages, making them unidentifiable to adversaries. Each packet is layer encrypted, and binary-padded so that it's indistinguishable from all other packets. Incoming packets are "mixed" with all other messages inside the node. That is, the node strips one layer of packet encryption, and adds a small random transmission delay, so that messages are not emitted in the same order as which they arrived. - Privacy Enhanced Applications (PEApps) that need to defend against network-level monitoring can utilize the Nym mixnet to protect against network-level surveillance. +Next, the message is sent to another mix node, decrypted and mixed again, then to a third mixnode for further mixing. Finally, the message is delivered to its destination gateway. - ### Revolutionising Privacy: An Incentivized Mixnet, the First of its Kind - Nym is the first mixnet to incentivise its node operators via a cryptocurrency: the `NYM` token. The tokenomic design of Nym ensures that nodes are motivated to provide top-notch performance and robust security, as they are financially rewarded for doing so. The video below contains an explanation of Nym's tokenomic design from Nym's Chief Scientist Claudia Diaz: +As long as there's enough traffic flowing through the nodes, even an adversary who can monitor the entire network cannot trace the packet flow through the system. - +Privacy Enhanced Applications (PEApps) that need to defend against network-level monitoring can utilize the Nym mixnet to protect against network-level surveillance. - ### ELI5 Understanding of the Implications of Nym - Nym is a type of technology that is designed to keep your online activities private from surveillance networks which track users of many online services. As well as protecting the contents of your messages - the data - Nym's design means that metadata - data about the data - is also kept private. This means that the location from which you sent your message, the time you did so, and a lot of information about your network connection is kept private: this is information that can be used to deanonymise users of other privacy systems, even if they employ encrypted messaging! +### Revolutionising Privacy: An Incentivized Mixnet, the First of its Kind +Nym is the first mixnet to incentivise its node operators via a cryptocurrency: the `NYM` token. The tokenomic design of Nym ensures that nodes are motivated to provide top-notch performance and robust security, as they are financially rewarded for doing so. The video below contains an explanation of Nym's tokenomic design from Nym's Chief Scientist Claudia Diaz: - Nym works by "mixing" your data with other users' data, making it much more difficult for anyone to single out and track just your information. + - This system is unique because it provides an incentive for people to participate and help improve the network, making it stronger and more secure for everyone. By breaking down Nym and understanding its implications, you can see why it's an important tool for anyone who values their privacy online. \ No newline at end of file +### ELI5 Understanding of the Implications of Nym +Nym is a type of technology that is designed to keep your online activities private from surveillance networks which track users of many online services. As well as protecting the contents of your messages - the data - Nym's design means that metadata - data about the data - is also kept private. This means that the location from which you sent your message, the time you did so, and a lot of information about your network connection is kept private: this is information that can be used to deanonymise users of other privacy systems, even if they employ encrypted messaging! + +Nym works by "mixing" your data with other users' data, making it much more difficult for anyone to single out and track just your information. + +This system is unique because it provides an incentive for people to participate and help improve the network, making it stronger and more secure for everyone. By breaking down Nym and understanding its implications, you can see why it's an important tool for anyone who values their privacy online. diff --git a/documentation/dev-portal/src/integrations/faq.md b/documentation/dev-portal/src/integrations/faq.md deleted file mode 100644 index a58f0e166e..0000000000 --- a/documentation/dev-portal/src/integrations/faq.md +++ /dev/null @@ -1,201 +0,0 @@ -# Integration FAQ - -On this page, you'll find links and frequently asked questions on how to get started on integrating your project with Nym's Mixnet and its blockchain, Nyx. - -## Links -### General Info -* [Nym Website](https://nymtech.net/) -* [Nym Mixnet Explorer](https://explorer.nymtech.net/) -* [Nyx Block Explorer](https://nym.explorers.guru/) - -### Codebase Info -* [Nym Platform Monorepo](https://github.com/nymtech/nym/) -* [Nym Project](https://github.com/nymtech/) - -### Documentation Info -* [Documentation](https://nymtech.net/docs/) -* Developer Portal - you are currently viewing the Developer Portal - -## Wallet Installation -The Nym wallet can be downloaded [here](https://nymtech.net/download/). - -You can find all the instructions related to setting up your wallet in the [docs](https://nymtech.net/docs/wallet.html), as well as instructions on how to build the wallet if there is not a downloadable version built for your operating system. - -### What are the machine hardware requirements for Nym Wallet? -About 16GB of RAM is recommended for the wallet. However you can expect an average memory usage of ~100MB. - - -## Interacting with the Nyx blockchain -### Where can I find information on the blockchain, such as RPC endpoints? -You can find most information required for integration in the [Cosmos Chain Registry](https://github.com/cosmos/chain-registry/blob/master/nyx/chain.json) and [Keplr Chain Registry](https://github.com/chainapsis/keplr-chain-registry/blob/main/cosmos/nyx.json) repositories. - -### How can I use `JSON-RPC` methods to interact with the Nyx blockchain? -There are multiple ways to use `JSON-RPC` methods to interact with the Nyx blockchain. Which method you use will depend on the type of application you are integrating Nyx interactions into. - -1. The standalone `nyxd` binary can be used for CLI wallets, interacting with smart contracts via the CLI, setting up RPC nodes, and even running validators. This is a version of the Cosmos Hub's `gaiad` binary compiled with Nyx chain configuration, and is written in `Go`. Instructions on setting up the `nyxd` binary can be found [here](https://nymtech.net/docs/nyx/interacting-with-chain.html). This is recommended for more complex commands. For full documentation check the [`gaiad documentation`](https://hub.cosmos.network/main/hub-overview/overview.html#). - -2. `CosmJS` is a Typescript library allowing for developers to interact with CosmosSDK blockchains from a Javascript or Typescript project. You can find it on Github [here](https://github.com/cosmos/cosmjs) and an explainer of its functionality [in the Cosmos Developer Portal](https://tutorials.cosmos.network/tutorials/7-cosmjs/1-cosmjs-intro.html). You can find a list of example apps which use CosmJS [here](https://codesandbox.io/examples/package/@cosmjs/stargate). - -3. The `Nym-CLI` tool, a standalone rust binary which can be built and used according to the [docs](https://nymtech.net/docs/tools/nym-cli.html) can be used in much the same way as `nyxd`. It is a bit simpler to use than the `nyxd` binary, but is not recommended for complex queries, and not all commands are currently implemented. A list of Nym CLI commands and example usage can be found [here](https://nymtech.net/docs/tools/nym-cli.html) - -### How do I generate an address/mnemonic for users to interact with? -**Nyxd** - -Use the following command, replacing `your_id` with the ID you want to use for your keypair: -``` -./nyxd keys add your_id --chain-id=nyx --gas=auto --gas-adjustment=1.4 --fees=7000unym -``` - -**Nym-CLI** -``` -./nym-cli account create -``` - -Both methods will generate a keypair and log the mnemonic in the console. - -**CosmJS** - -You can find example code for keypair generation [here](https://tutorials.cosmos.network/tutorials/7-cosmjs/2-first-steps.html#testnet-preparation). - -### How to get block information like block height, block hash, block time as so on? -**Nyxd** - -You would use one of the subcommands returned by this command: -``` -./nyxd query tx --chain-id=nyx --gas=auto --gas-adjustment=1.4 --fees=7000unym -``` - -**Nym-CLI** -``` -./nym-cli block current-height -``` - -**CosmJS** - -`CosmJS` documentation can be found [here](https://cosmos.github.io/cosmjs/). We will be working on example code blocks soon. - -### How to get account/address balance to check there is enough coins to withdraw? -**Nyxd** -``` -./nyxd query bank balances
--chain-id=nyx --gas=auto --gas-adjustment=1.4 --fees=7000unym -``` - -**Nym-CLI** -``` -./nym-cli account balance -``` - -**CosmJS** - -`CosmJS` documentation can be found [here](https://cosmos.github.io/cosmjs/). We will be working on example code blocks soon. - -### How do I transfer tokens to another address? -**Nyxd** -``` -./nyxd tx bank send [from_key_or_address] [to_address] [amount] --chain-id=nyx --gas=auto --gas-adjustment=1.4 --fees=7000unym -``` - -**Nym-CLI** -``` -./nym-cli account send TARGET_ADDRESS AMOUNT -``` -**CosmJS** - -`CosmJS` documentation can be found [here](https://cosmos.github.io/cosmjs/). We will be working on example code blocks soon. - -### Does the address support the inclusion of a `memo` or `destinationTag` when doing the transfer? -Yes, it is supported. - -### Can I use my Ledger hardware wallet to interact with the Nyx blockchain? -Yes. Follow the instructions in the [Ledger support for Nyx documentation](https://nymtech.net/docs/nyx/ledger-live.html). - -### Where can I find network details such as deployed smart contract addresses? -In the [`network defaults`](https://github.com/nymtech/nym/blob/master/common/network-defaults/src/mainnet.rs) file. - -## `NYM` Token -The token used to reward mixnet infrastructure operators - `NYM` - is one of the native tokens of the Nyx blockchain. The other token is `NYX`. - -`NYM` is used to incentivise the mixnet, whereas `NYX` is used to secure the Nyx blockchain via Validator staking. - -> Integration with Nym's technology stack will most likely involve using `NYM` if you do need to interact with the Nyx blockchain and transfer tokens. - -### I've seen an ERC20 representation of `NYM` on Ethereum - what's this and how do I use it? - -We use the [Gravity Bridge](https://github.com/Gravity-Bridge) blockchain to bridge an ERC20 representation of `NYM` between the Cosmos ecosystem of IBC-enabled chains and Ethereum mainnet. Gravity Bridge is its own IBC-enabled CosmosSDK chain, which interacts with a smart contract deployed on Ethereum mainnet. - -> The ERC20 representation of `NYM` **cannot** be used with the mixnet; only the native Cosmos representation is usable for staking or bonding nodes. - -If you need to transfer tokens across the bridge, we recommend users use Cosmostation's [spacestation.zone](https://spacestation.zone/) dApp with Metamask and Keplr. - -### What is Circulating Supply and how to find out the distribution amount? - -Circulating supply is the total number of available `NYM`. `NYM` is currently present on the IBC-enabled Nyx blockchain, as well as in ERC20 form on Ethereum Mainnet. - -The Validator API endpoints can be found via the [Swagger Documentation](https://validator.nymtech.net/api/swagger/index.html). The following endpoints can be called to retrieve the correct distribution amount and circulating supply within Nym. - -Using this API endpoint returns information about the circulating supply of Nym tokens: - -``` -/circulating-supply -``` -Query Response: - - { - "total_supply": { - "denom": "unym", - "amount": "1000000000000000" - }, - "mixmining_reserve": { - "denom": "unym", - "amount": "241105338883248" - }, - "vesting_tokens": { - "denom": "unym", - "amount": "390255200928865" - }, - "circulating_supply": { - "denom": "unym", - "amount": "368639460187887" - } - } - -- `total_supply`- The total number of NYM tokens that have been created and can exist, including those that are currently in circulation and those that are reserved for various purposes. - -- `mixmining_reserved`- The number of NYM tokens that are reserved for the mixnet miners who help to power the Nym network. - -- `vesting_tokens`- The number of NYM tokens that are subject to vesting, meaning they are gradually released over time to certain stakeholders such as the team, advisors, and early investors. - -- `circulating_supply`- The number of NYM tokens that are currently in circulation and available to be traded on the open market, which is calculated by subtracting the `mixmining_reserved` and `vesting_tokens` from the `total_supply`. - -Using this API endpoint returns the current value of the total supply of NYM tokens: - -``` -/circulating-supply/total-supply-value -``` -Query Response: - - 1000000000.0 - -> The maximum number of `NYM` tokens that can ever be created is 1 billion. - -Using this API endpoint returns the current value of the circulating supply of NYM tokens: - -``` -/circulating-supply/circulating-supply-value -``` -Query Response: - - 368639460.187887 - -> This refers to the present quantity of `NYM` tokens that are actively in circulation. - - -## Sending traffic through the Nym mixnet -### Is the mixnet free to use? -For the moment then yes, the mixnet is free to use. There are no limits on the amount of traffic that an app can send through the mixnet. - -### Do I need to run my own gateway to send application traffic through the mixnet? -No, although we do recommend that apps that wish to integrate look into running some of their own infrastructure such as gateways in order to assure uptime. - -### How can I find out if an application is already supported by network requester services? -You can check the [default allowed list](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) file to see which application traffic is whitelisted by default. If the domain is present on that list, it means that existing [network requesters](https://nymtech.net/docs/nodes/network-requester-setup.html) can be used to privacy-protect your application traffic. Simply use [NymConnect](../quickstart/nymconnect-gui.md) to connect to this service through the mixnet. diff --git a/documentation/dev-portal/src/integrations/mixnet-integration.md b/documentation/dev-portal/src/integrations/mixnet-integration.md index f1fa576265..91e6c2d559 100644 --- a/documentation/dev-portal/src/integrations/mixnet-integration.md +++ b/documentation/dev-portal/src/integrations/mixnet-integration.md @@ -35,7 +35,7 @@ You can find examples of how to utilise this client in the [Quickstart](../quick In order to ensure uptime and reliability, it is recommended that you run some pieces of mixnet infrastructure. What infrastructure is necessary to run depends on the architecture of your application, and the endpoints that it needs to hit! * If you're running a purely P2P application, then just integrating clients and having some method of sharing addresses should be enough to route your traffic through the mixnet. -* If you're wanting to place the mixnet between your users' application instances and a server-based backend, you can use the [network requester](https://nymtech.net/docs/nodes/network-requester-setup.html) service provider binary to proxy these requests to your application backend, with the mixnet 'between' the user and your service, in order to prevent metadata leakage being broadcast to the internet. +* If you're wanting to place the mixnet between your users' application instances and a server-based backend, you can use the [network requester](https://nymtech.net/operators/nodes/network-requester-setup.html) service provider binary to proxy these requests to your application backend, with the mixnet 'between' the user and your service, in order to prevent metadata leakage being broadcast to the internet. * If you're wanting to route RPC requests through the mixnet to a blockchain, you will need to look into setting up some sort of service that does the transaction broadcasting for you. You can find examples of such projects on the [community applications](../community-resources/community-applications-and-guides.md) page. ## Example application traffic flow diff --git a/documentation/dev-portal/src/introduction.md b/documentation/dev-portal/src/introduction.md index 7335fab32b..c28c708921 100644 --- a/documentation/dev-portal/src/introduction.md +++ b/documentation/dev-portal/src/introduction.md @@ -2,4 +2,4 @@ Welcome to the Nym Developer Portal, containing quickstart resources, user manuals, integration information, and tutorials outlining to start building privacy enhanced apps. -For more in-depth information about nodes, network traffic flows, etc check out the [docs](https://nymtech.net/docs). +For more in-depth information about nodes, network traffic flows, clients, coconut etc check out the [docs](https://nymtech.net/docs). If you are looking for information and setup guides for the various pieces of Nym mixnet infrastructure (mix nodes, gateways and network requesters) and Nyx blockchain validators see the **new [Operators Guides](https://nymtech.net/operators)** book. diff --git a/documentation/dev-portal/src/quickstart/socks-proxy.md b/documentation/dev-portal/src/quickstart/socks-proxy.md index 75ac27816a..88c4533d95 100644 --- a/documentation/dev-portal/src/quickstart/socks-proxy.md +++ b/documentation/dev-portal/src/quickstart/socks-proxy.md @@ -12,7 +12,7 @@ If you are using a different operating system, head over to the [Building from S ### Initialise your socks5 client -Use the following command to initialise your socks5 client with the address of a Nym-operated [Network Requester](https://nymtech.net/docs/nodes/network-requester-setup.html) as a provider (the endpoint that will be proxying your traffic out of the mixnet) for ease: +Use the following command to initialise your socks5 client with the address of a Nym-operated [Network Requester](https://nymtech.net/docs/nodes/network-requester.html) as a provider (the endpoint that will be proxying your traffic out of the mixnet) for ease: ``` ./nym-socks5-client init --id quickstart --provider Entztfv6Uaz2hpYHQJ6JKoaCTpDL5dja18SuQWVJAmmx.Cvhn9rBJw5Ay9wgHcbgCnVg89MPSV5s2muPV2YF1BXYu@Fo4f4SQLdoyoGkFae5TpVhRVoXCF8UiypLVGtGjujVPf diff --git a/documentation/dev-portal/src/tutorials/simple-service-provider/overview.md b/documentation/dev-portal/src/tutorials/simple-service-provider/overview.md index ee3d148e7d..be73bdfe90 100644 --- a/documentation/dev-portal/src/tutorials/simple-service-provider/overview.md +++ b/documentation/dev-portal/src/tutorials/simple-service-provider/overview.md @@ -6,7 +6,7 @@ This tutorial involves writing two pieces of code in Typescript: - A **User Client** (UC) with which you can access the mixnet through a browser on your local machine. You will use this to communicate with the second component outlined below. - A **Service Provider** (SP) which can communicate with the UC via the mixnet. -Additionally you will learn how to configure a pair of **Nym Websocket Clients** which both components use to connect to and communicate with the mixnet. +Additionally you will learn how to configure a pair of **Nym Websocket Clients** which both components use to connect to and communicate with the Mixnet. > SPs usually run on remote servers to assure reliable uptime and to unlink sender and receiver metadata. For demonstration purposes however, you will run both components on your local machine, looping messages through the mixnet to yourself. @@ -58,7 +58,7 @@ Notice that this tutorial attempts to use very few external libraries (the User ```admonish note title="Sidenote: What is a Service Provider?" 'Service Provider' is a catchall name used to refer to any type of app that can communicate with the mixnet via a Nym client. -The first SP to have been released is the [Network Requester](https://nymtech.net/docs/nodes/network-requester-setup.html) - a binary that receives a network request from the mixnet, performs that request (e.g. authenticating with a message server and receiving new messages for a user) and then passes the response back to the user who requested it anonymously, shielding their metadata from the message server. +The first SP to have been released is the [Network Requester](https://nymtech.net/docs/nodes/network-requester.html) - a binary that receives a network request from the mixnet, performs that request (e.g. authenticating with a message server and receiving new messages for a user) and then passes the response back to the user who requested it anonymously, shielding their metadata from the message server. The SP you will build in this tutorial is far more simple than this. It is just to show you how to approach building something that can: * connect to the mixnet, @@ -67,4 +67,4 @@ The SP you will build in this tutorial is far more simple than this. It is just However, once you see how easy it is to integrate with the mixnet for traffic transport, you will be able to build apps with real-world uses easily. ``` - \ No newline at end of file + diff --git a/documentation/docs/src/clients/websocket-client.md b/documentation/docs/src/clients/websocket-client.md index f0980ad9ae..103112d63e 100644 --- a/documentation/docs/src/clients/websocket-client.md +++ b/documentation/docs/src/clients/websocket-client.md @@ -122,7 +122,7 @@ All of these code examples will do the following: By varying the message content, you can easily build sophisticated service provider apps. For example, instead of printing the response received from the mixnet, your service provider might take some action on behalf of the user - perhaps initiating a network request, a blockchain transaction, or writing to a local data store. -> You can find an example of building both frontend and service provider code with the websocket client in the [Simple Service Provider Tutorial](https://nymtech.net/developers/tutorials/simple-service-provider.html) in the Developer Portal. +> You can find an example of building both frontend and service provider code with the websocket client in the [Simple Service Provider Tutorial](https://nymtech.net/developers/tutorials/simple-service-provider/simple-service-provider.html) in the Developer Portal. ### Message Types There are a small number of messages that your application sends up the websocket to interact with the native client, as follows. diff --git a/documentation/docs/src/introduction.md b/documentation/docs/src/introduction.md index 9964ec5b75..ac5d425a02 100644 --- a/documentation/docs/src/introduction.md +++ b/documentation/docs/src/introduction.md @@ -4,7 +4,7 @@ This is Nym's technical documentation, containing information and setup guides a If you are looking for information and setup guides for the various pieces of Nym mixnet infrastructure (mix nodes, gateways and network requesters) and Nyx blockchain validators see the **new [Operators Guides](https://nymtech.net/operators)** book. -If you are new to Nym and want to learn about the mixnet, explore kickstart options and demos, learn how to integrate with the network, and follow developer tutorials check out the [Developer Portal](https://nymtech.net/developers/). +If you are new to Nym and want to learn about the mixnet, explore kickstart options and demos, learn how to integrate with the network, and follow developer tutorials check out the [Developer Portal](https://nymtech.net/developers/) where you can find also our [FAQ section](https://nymtech.net/developers/faq/general-faq.md). ## Popular pages **Network Architecture:** @@ -27,4 +27,4 @@ If you are new to Nym and want to learn about the mixnet, explore kickstart opti **Wallets** * [Desktop](./wallet/desktop-wallet.md) -* [CLI](./wallet/cli-wallet.md) \ No newline at end of file +* [CLI](./wallet/cli-wallet.md) diff --git a/documentation/docs/src/nodes/mixnode.md b/documentation/docs/src/nodes/mixnode.md index b093c6f0b4..8565f7be0a 100644 --- a/documentation/docs/src/nodes/mixnode.md +++ b/documentation/docs/src/nodes/mixnode.md @@ -1,6 +1,6 @@ # Mix Nodes -> The mix node setup and maintenance guide has migrated to the [Operator Guides book](https://nymtech.net/developers/nodes/mix-node-setup.html). +> The mix node setup and maintenance guide has migrated to the [Operator Guides book](https://nymtech.net/operators/nodes/mix-node-setup.html). Mix nodes are the backbone of the mixnet. These are the nodes that perform 'mix mining', otherwise known simply as 'mixing'. @@ -14,4 +14,4 @@ Mix nodes are rewarded according to their quality of service, and the probabilit * [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf) section 4 * [Nym Blog: Mix node deepdive](https://blog.nymtech.net/nym-mixnodes-deep-dive-d2b91917f097) * [Mixnet Traffic Flow overview](../architecture/traffic-flow.md) -* [Reward Sharing for Mixnets](https://nymtech.net/nym-cryptoecon-paper.pdf) \ No newline at end of file +* [Reward Sharing for Mixnets](https://nymtech.net/nym-cryptoecon-paper.pdf) diff --git a/documentation/docs/src/nodes/network-requester.md b/documentation/docs/src/nodes/network-requester.md index ac083a3143..da9fff6a64 100644 --- a/documentation/docs/src/nodes/network-requester.md +++ b/documentation/docs/src/nodes/network-requester.md @@ -1,6 +1,6 @@ # Network Requester -> The network requester setup and maintenance guide has moved to the [Operator Guides book](https://nymtech.net/developers/nodes/network-requester-setup.html). +> The network requester setup and maintenance guide has moved to the [Operator Guides book](https://nymtech.net/operators/nodes/network-requester-setup.html). Network requesters are the first instance of the catch-all term 'service', or 'service providers'. In essence, think of services as being the part of the mixnet infrastructure that let you _do_ something, such as access emails, messaging service backends, or blockchains via the mixnet. @@ -19,4 +19,4 @@ This default whitelist is useful for knowing that the majority of Network reques ## Further reading * [Nym Blog: Network Requester deepdive](https://blog.nymtech.net/tech-deepdive-network-requesters-e5359a6cc31c) -* [Nym Blog: Choose Your Character](https://blog.nymtech.net/choose-your-character-an-overview-of-nym-network-actors-19e6a9808540) \ No newline at end of file +* [Nym Blog: Choose Your Character](https://blog.nymtech.net/choose-your-character-an-overview-of-nym-network-actors-19e6a9808540) diff --git a/documentation/docs/src/nyx/ledger-live.md b/documentation/docs/src/nyx/ledger-live.md index 031834fa24..968dd2e25b 100644 --- a/documentation/docs/src/nyx/ledger-live.md +++ b/documentation/docs/src/nyx/ledger-live.md @@ -4,7 +4,7 @@ Use the following instructions to interact with the Nyx blockchain - either with ## Prerequisites * Download and install [Ledger Live](https://www.ledger.com/ledger-live). -* Compile the `nyxd` binary as per the instructions [here](https://nymtech.net/operators/nodes/validator-setup.md#building-the-nym-validator). Stop after you can successfully run `nyxd` and get the helptext in your console output. +* Compile the `nyxd` binary as per the instructions [here](https://nymtech.net/operators/nodes/validator-setup.html#building-the-nym-validator). Stop after you can successfully run `nyxd` and get the helptext in your console output. ## Prepare your Ledger App * Plug in your Ledger device diff --git a/documentation/docs/src/nyx/rpc-node.md b/documentation/docs/src/nyx/rpc-node.md index dc48d68409..352b689bed 100644 --- a/documentation/docs/src/nyx/rpc-node.md +++ b/documentation/docs/src/nyx/rpc-node.md @@ -4,6 +4,6 @@ RPC Nodes (which might otherwise be referred to as 'Lite Nodes' or just 'Full No You may want to set up an RPC Node for querying the blockchain, or in order to have an endpoint that your app can use to send transactions. -In order to set up an RPC Node, simply follow the instructions to set up a [Validator](https://nymtech.net/operators/nodes/validator-setup.md), but **exclude the `nyxd tx staking create-validator` command**. +In order to set up an RPC Node, simply follow the instructions to set up a [Validator](https://nymtech.net/operators/nodes/validator-setup.html), but **exclude the `nyxd tx staking create-validator` command**. -If you want to fast-sync your node, check out the Polkachu snapshot and their other [resources](https://polkachu.com/seeds/nym). \ No newline at end of file +If you want to fast-sync your node, check out the Polkachu snapshot and their other [resources](https://polkachu.com/seeds/nym). diff --git a/documentation/operators/src/nodes/maintenance.md b/documentation/operators/src/nodes/maintenance.md index 7f0416ea9d..e29b80eb25 100644 --- a/documentation/operators/src/nodes/maintenance.md +++ b/documentation/operators/src/nodes/maintenance.md @@ -10,7 +10,7 @@ A `build-info` command prints the build information like commit hash, rust versi For example `./target/debug/nym-network-requester --no-banner build-info --output json` will return: -``` +```sh {"binary_name":"nym-network-requester","build_timestamp":"2023-07-24T15:38:37.00657Z","build_version":"1.1.23","commit_sha":"c70149400206dce24cf20babb1e64f22202672dd","commit_timestamp":"2023-07-24T14:45:45Z","commit_branch":"feature/simplify-cli-parsing","rustc_version":"1.71.0","rustc_channel":"stable","cargo_profile":"debug"} ``` @@ -46,7 +46,7 @@ You can either do this graphically via the Desktop Wallet, or the CLI. ![Node Settings Page](../images/wallet-screenshots/node_settings.png) ### Updating node information via the CLI -If you want to bond your `` via the CLI, then check out the [relevant section in the Nym CLI](https://nymtech.net/docs/tools/nym-cli.md#upgrade-a-mix-node) docs. +If you want to bond your `` via the CLI, then check out the [relevant section in the Nym CLI](https://nymtech.net/docs/tools/nym-cli.html#upgrade-a-mix-node) docs. ### Upgrading Network Requester to >= v1.1.10 from ``` Copy the old keys from your client to the network-requester configuration that was created above: -``` +```sh cp -vr ~/.nym/clients/myoldclient/data/* ~/.nym/service-providers/network-requester//data ``` Edit the configuration to match what you used on your client. Specifically, edit the configuration file at: -``` +```sh ~/.nym/service-providers/network-requester//config/config.toml ``` Ensure that the fields `gateway_id`, `gateway_owner`, `gateway_listener` in the new config match those in the old client config at: -``` +```sh ~/.nym/clients/myoldclient/config/config.toml ``` @@ -115,7 +115,8 @@ Assuming both machines are remote VPS. * Make sure your `~/.ssh/.pub` is in both of the machines `~/.ssh/authorized_keys` file * Create a `mixnodes` folder in the target VPS. Ssh in from your terminal and run: -``` + +```sh # in case none of the nym configs was created previously mkdir ~/.nym @@ -123,7 +124,7 @@ mkdir ~/.nym mkdir ~/.nym/mixnodes ``` * Move the node data (keys) and config file to the new machine by opening a local terminal (as that one's ssh key is authorized in both of the machines) and running: -``` +```sh scp -r -3 @:~/.nym/mixnodes/ @:~/.nym/mixnodes/ ``` * Re-run init (remember that init doesn't overwrite existing keys) to generate a config with the new listening address etc. @@ -134,7 +135,7 @@ scp -r -3 @:~/.nym/mixnodes/ ` is now ready to receive traffic, your server may not be. The following commands will allow you to set up a firewall using `ufw`. -``` +```sh # check if you have ufw installed ufw version @@ -150,7 +151,7 @@ sudo ufw status Finally open your `` p2p port, as well as ports for ssh and ports for verloc and measurement pings: -``` +```sh # for mix node sudo ufw allow 1789,1790,8000,22/tcp @@ -165,11 +166,11 @@ sudo ufw allow 1317,26656,26660,22,80,443/tcp ``` Check the status of the firewall: -``` +```sh sudo ufw status ``` -For more information about your node's port configuration, check the [port reference table](https://nymtech.net/docs/nodes/gateway-setup.html#ports) below. +For more information about your node's port configuration, check the [port reference table](./maintenance.md#gateway-port-reference) below. ### Automating your node with nohup, tmux and systemd @@ -179,7 +180,7 @@ Although it’s not totally necessary, it's useful to have the mix node automati `nohup` is a command with which your terminal is told to ignore the `HUP` or 'hangup' signal. This will stop the node process ending if you kill your session. -``` +```sh nohup ./ run --id # where `` is the id you set during the `init` command and depends on which node you starting ``` @@ -207,17 +208,17 @@ No when you installed tmux on your VPS, let's run a mix node on tmux, which allo * Pause your `` * Start tmux with the command -``` +```sh tmux ``` * The tmux terminal should open in the same working directory, just the layout changed into tmux default layout. * Start the `` again with a command: -``` +```sh ./ run --id ``` * Now, without closing the tmux window, you can close the whole terminal and the `` (and any other process running in tmux) will stay active. * Next time just start your teminal, ssh into the VPS and run the following command to attach back to your previous session: -``` +```sh tmux attach-session ``` * To see keybinding options of tmux press `ctrl`+`b` and after 1 second `?` @@ -293,7 +294,7 @@ WantedBy=multi-user.target Now enable and start your requester: -``` +```sh systemctl enable nym-network-requester.service systemctl start nym-network-requester.service @@ -313,10 +314,10 @@ StartLimitInterval=350 StartLimitBurst=10 [Service] -User=nyx # change to your user +User= # change to your user Type=simple -Environment="LD_LIBRARY_PATH=/home/youruser/path/to/nyx/binaries" # change to correct path -ExecStart=/home/youruser/path/to/nyx/binaries/nymd start # change to correct path +Environment="LD_LIBRARY_PATH=/home//" # change to correct path +ExecStart=/home///nymd start # change to correct path Restart=on-failure RestartSec=30 LimitNOFILE=infinity @@ -327,11 +328,11 @@ WantedBy=multi-user.target Proceed to start it with: -``` +```sh systemctl daemon-reload # to pickup the new unit file systemctl enable nymd # to enable the service systemctl start nymd # to actually start the service -journalctl -f # to monitor system logs showing the service start +journalctl -f -u nymd # to monitor system logs showing the service start ``` ##### Following steps for Nym Mixnet nodes @@ -344,9 +345,13 @@ If you have built nym in the `$HOME` directory on your server, and your username Then run: +```sh +systemctl daemon-reload # to pickup the new unit file ``` + +```sh # for mix node -systemctl enable nym-mix node.service +systemctl enable nym-mixnode.service # for gateway systemctl enable nym-gateway.service @@ -354,7 +359,7 @@ systemctl enable nym-gateway.service Start your node: -``` +```sh # for mix node service nym-mixnode start @@ -365,6 +370,16 @@ service nym-gateway start This will cause your node to start at system boot time. If you restart your machine, the node will come back up automatically. +You can monitor system logs of your node by running: +```sh +journalctl -f -u .service +``` + +Or check a status by running: +```sh +systemctl status .service +``` + You can also do `service stop` or `service restart`. Note: if you make any changes to your systemd script after you've enabled it, you will need to run: @@ -383,7 +398,7 @@ Linux machines limit how many open files a user is allowed to have. This is call If you see errors such as: -``` +```sh Failed to accept incoming connection - Os { code: 24, kind: Other, message: "Too many open files" } ``` @@ -397,8 +412,8 @@ The ulimit setup is relevant for maintenance of nym mix node only. Query the `ulimit` of your `` with: -``` -# for nym-, nym-gateway and nym-network requester: +```sh +# for nym-mixnode, nym-gateway and nym-network requester: grep -i "open files" /proc/$(ps -A -o pid,cmd|grep | grep -v grep |head -n 1 | awk '{print $1}')/limits # for nyx validator: @@ -409,7 +424,7 @@ grep -i "open files" /proc/$(ps -A -o pid,cmd|grep nymd | grep -v grep |head -n You'll get back the hard and soft limits, which looks something like this: -``` +```sh Max open files 65536 65536 files ``` @@ -417,26 +432,26 @@ If your output is **the same as above**, your node will not encounter any `ulimi However if either value is `1024`, you must raise the limit via the systemd service file. Add the line: -``` +```sh LimitNOFILE=65536 ``` Reload the daemon: -``` +```sh systemctl daemon-reload ``` or execute this as root for system-wide setting of `ulimit`: -``` +```sh echo "DefaultLimitNOFILE=65535" >> /etc/systemd/system.conf ``` Reboot your machine and restart your node. When it comes back, use: -``` +```sh # for nym-mixnode, nym-gateway and nym-network requester: -cat /proc/$(pidof )/limits | grep "Max open files"` to make sure the limit has changed to 65535. +cat /proc/$(pidof )/limits | grep "Max open files" # for validator cat /proc/$(pidof nym-validator)/limits | grep "Max open files" @@ -447,7 +462,7 @@ Make sure the limit has changed to 65535. In case you chose tmux option for mix node automatization, see your `ulimit` list by running: -``` +```sh ulimit -a # watch for the output line -n @@ -456,13 +471,13 @@ ulimit -a You can change it either by running a command: -``` +```sh ulimit -u -n 4096 ``` or editing `etc/security/conf` and add the following lines: -``` +```sh # Example hard limit for max opened files username hard nofile 4096 @@ -479,7 +494,7 @@ On some services (AWS, Google, etc) the machine's available bind address is not For example, on a Google machine, you may see the following output from the `ifconfig` command: -``` +```sh ens4: flags=4163 mtu 1460 inet 10.126.5.7 netmask 255.255.255.255 broadcast 0.0.0.0 ... @@ -492,7 +507,7 @@ The `ens4` interface has the IP `10.126.5.7`. But this isn't the public IP of th Trying `nym-mixnode init --host 36.68.243.18`, you'll get back a startup error saying `AddrNotAvailable`. This is because the mix node doesn't know how to bind to a host that's not in the output of `ifconfig`. The right thing to do in this situation is to init with a command: -``` +```sh ./nym-mixnode init --host 10.126.5.7 --announce-host 36.68.243.18 ``` @@ -513,13 +528,13 @@ The endpoint is a particularly common for mix node operators as it can provide a Using this API endpoint returns information about the Reward Estimation: -``` +```sh /status/mixnode//reward-estimation ``` Query Response: -``` +```sh "estimation": { "total_node_reward": "942035.916721770541325331", "operator": "161666.263307386408152071", @@ -546,19 +561,19 @@ Query Response: Install `nginx` and allow the 'Nginx Full' rule in your firewall: -``` +```sh sudo ufw allow 'Nginx Full' ``` Check nginx is running via systemctl: -``` +```sh systemctl status nginx ``` Which should return: -``` +```sh ● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2018-04-20 16:08:19 UTC; 3 days ago @@ -574,7 +589,7 @@ Which should return: Proxying your validator's port `26657` to nginx port `80` can then be done by creating a file with the following at `/etc/nginx/conf.d/validator.conf`: -``` +```sh server { listen 80; listen [::]:80; @@ -591,7 +606,7 @@ server { Followed by: -``` +```sh sudo apt install certbot nginx python3 certbot --nginx -d nym-validator.yourdomain.com -m you@yourdomain.com --agree-tos --noninteractive --redirect ``` @@ -606,7 +621,7 @@ These commands will get you an https encrypted nginx proxy in front of the API. Configure Prometheus with the following commands (adapted from NodesGuru's [Agoric setup guide](https://nodes.guru/agoric/setup-guide/en)): -``` +```sh echo 'export OTEL_EXPORTER_PROMETHEUS_PORT=9464' >> $HOME/.bashrc source ~/.bashrc sed -i '/\[telemetry\]/{:a;n;/enabled/s/false/true/;Ta}' $HOME/.nymd/config/app.toml diff --git a/documentation/operators/src/nodes/network-requester-setup.md b/documentation/operators/src/nodes/network-requester-setup.md index b89dc4d0b2..640f103a65 100644 --- a/documentation/operators/src/nodes/network-requester-setup.md +++ b/documentation/operators/src/nodes/network-requester-setup.md @@ -263,7 +263,7 @@ It is easy to add new domains and services to your network requester - simply fi How to go about this? Have a look in your nym-network-requester config directory: ``` -ls $HOME/.nym/service-providers/network-requester/ +ls -lt $HOME/.nym/service-providers/network-requester/*/data | grep "list" # returns: allowed.list unknown.list ``` diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index bd6fed0ae6..79323fe3fe 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "explorer-api" -version = "1.1.28" +version = "1.1.29" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/explorer-api/explorer-client/src/lib.rs b/explorer-api/explorer-client/src/lib.rs index acb1cc7e67..6a8790bd34 100644 --- a/explorer-api/explorer-client/src/lib.rs +++ b/explorer-api/explorer-client/src/lib.rs @@ -1,3 +1,4 @@ +#[cfg(not(target_arch = "wasm32"))] use std::time::Duration; use reqwest::StatusCode; diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index 7fb1cc29d6..d54d8e1ee7 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-gateway" -version = "1.1.28" +version = "1.1.29" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", @@ -37,7 +37,7 @@ serde_json = { workspace = true } sqlx = { version = "0.5", features = [ "runtime-tokio-rustls", "sqlite", "macros", "migrate", ] } subtle-encoding = { version = "0.5", features = ["bech32-preview"] } thiserror = "1" -tokio = { version = "1.24.1", features = [ "rt-multi-thread", "net", "signal", "fs", ] } +tokio = { workspace = true, features = [ "rt-multi-thread", "net", "signal", "fs", "time" ] } tokio-stream = { version = "0.1.11", features = ["fs"] } tokio-tungstenite = "0.14" tokio-util = { version = "0.7.4", features = ["codec"] } diff --git a/gateway/src/node/client_handling/active_clients.rs b/gateway/src/node/client_handling/active_clients.rs index d2de2cc5b5..280027dacd 100644 --- a/gateway/src/node/client_handling/active_clients.rs +++ b/gateway/src/node/client_handling/active_clients.rs @@ -1,13 +1,23 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::node::client_handling::websocket::message_receiver::MixMessageSender; use dashmap::DashMap; use nym_sphinx::DestinationAddressBytes; use std::sync::Arc; +use super::websocket::message_receiver::{IsActiveRequestSender, MixMessageSender}; + #[derive(Clone)] -pub(crate) struct ActiveClientsStore(Arc>); +pub(crate) struct ActiveClientsStore(Arc>); + +#[derive(Clone)] +pub(crate) struct ClientIncomingChannels { + // Mix messages coming from the mixnet to the handler of a client. + pub mix_message_sender: MixMessageSender, + + // Requests sent from the handler of one client to the handler of other clients. + pub is_active_request_sender: IsActiveRequestSender, +} impl ActiveClientsStore { /// Creates new instance of `ActiveClientsStore` to store in-memory handles to all currently connected clients. @@ -21,13 +31,13 @@ impl ActiveClientsStore { /// # Arguments /// /// * `client`: address of the client for which to obtain the handle. - pub(crate) fn get(&self, client: DestinationAddressBytes) -> Option { + pub(crate) fn get(&self, client: DestinationAddressBytes) -> Option { let entry = self.0.get(&client)?; let handle = entry.value(); // if the entry is stale, remove it from the map // if handle.is_valid() { - if !handle.is_closed() { + if !handle.mix_message_sender.is_closed() { Some(handle.clone()) } else { // drop the reference to the map to prevent deadlocks @@ -52,8 +62,19 @@ impl ActiveClientsStore { /// /// * `client`: address of the client for which to insert the handle. /// * `handle`: the sender channel for all mix packets to be pushed back onto the websocket - pub(crate) fn insert(&self, client: DestinationAddressBytes, handle: MixMessageSender) { - self.0.insert(client, handle); + pub(crate) fn insert( + &self, + client: DestinationAddressBytes, + handle: MixMessageSender, + is_active_request_sender: IsActiveRequestSender, + ) { + self.0.insert( + client, + ClientIncomingChannels { + mix_message_sender: handle, + is_active_request_sender, + }, + ); } /// Get number of active clients in store diff --git a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs index 0fe930a96d..1bbd85b5f1 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs @@ -1,28 +1,39 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::node::client_handling::websocket::connection_handler::{ClientDetails, FreshHandler}; -use crate::node::client_handling::websocket::message_receiver::MixMessageReceiver; -use crate::node::storage::error::StorageError; -use crate::node::storage::Storage; -use futures::StreamExt; +use futures::{ + future::{FusedFuture, OptionFuture}, + FutureExt, StreamExt, +}; use log::*; -use nym_gateway_requests::iv::IVConversionError; -use nym_gateway_requests::types::{BinaryRequest, ServerResponse}; -use nym_gateway_requests::{ClientControlRequest, GatewayRequestsError}; +use nym_gateway_requests::{ + iv::{IVConversionError, IV}, + types::{BinaryRequest, ServerResponse}, + ClientControlRequest, GatewayRequestsError, +}; use nym_sphinx::forwarding::packet::MixPacket; -use rand::{CryptoRng, Rng}; -use std::convert::TryFrom; -use std::process; -use thiserror::Error; -use tokio::io::{AsyncRead, AsyncWrite}; -use tokio_tungstenite::tungstenite::protocol::Message; - -use crate::node::client_handling::bandwidth::Bandwidth; -use crate::node::client_handling::FREE_TESTNET_BANDWIDTH_VALUE; -use nym_gateway_requests::iv::IV; use nym_task::TaskClient; use nym_validator_client::coconut::CoconutApiError; +use rand::{CryptoRng, Rng}; +use thiserror::Error; +use tokio::io::{AsyncRead, AsyncWrite}; +use tokio_tungstenite::tungstenite::{protocol::Message, Error as WsError}; + +use std::{convert::TryFrom, process, time::Duration}; + +use crate::node::{ + client_handling::{ + bandwidth::Bandwidth, + websocket::{ + connection_handler::{ClientDetails, FreshHandler}, + message_receiver::{ + IsActive, IsActiveRequestReceiver, IsActiveResultSender, MixMessageReceiver, + }, + }, + FREE_TESTNET_BANDWIDTH_VALUE, + }, + storage::{error::StorageError, Storage}, +}; #[derive(Debug, Error)] pub(crate) enum RequestHandlingError { @@ -97,6 +108,11 @@ pub(crate) struct AuthenticatedHandler { inner: FreshHandler, client: ClientDetails, mix_receiver: MixMessageReceiver, + // Occasionally the handler is requested to ping the connected client for confirm that it's + // active, such as when a duplicate connection is detected. This hashmap stores the oneshot + // senders that are used to return the result of the ping to the handler requesting the ping. + is_active_request_receiver: IsActiveRequestReceiver, + is_active_ping_pending_reply: Option<(u64, IsActiveResultSender)>, } // explicitly remove handle from the global store upon being dropped @@ -127,11 +143,14 @@ where fresh: FreshHandler, client: ClientDetails, mix_receiver: MixMessageReceiver, + is_active_request_receiver: IsActiveRequestReceiver, ) -> Self { AuthenticatedHandler { inner: fresh, client, mix_receiver, + is_active_request_receiver, + is_active_ping_pending_reply: None, } } @@ -351,6 +370,29 @@ where } } + /// Handles pong message received from the client. + /// If the client is still active, the handler that requested the ping will receive a reply. + async fn handle_pong(&mut self, msg: Vec) { + if let Ok(msg) = msg.try_into() { + let msg = u64::from_be_bytes(msg); + trace!("Received pong from client: {}", msg); + if let Some((tag, _)) = &self.is_active_ping_pending_reply { + if tag == &msg { + debug!("Reporting back to the handler that the client is still active"); + let tx = self.is_active_ping_pending_reply.take().unwrap().1; + if let Err(err) = tx.send(IsActive::Active) { + warn!("Failed to send pong reply back to the requesting handler: {err:?}"); + } + } else { + warn!( + "Received pong reply from the client with unexpected tag: {}", + msg + ); + } + } + } + } + /// Attempts to handle websocket message received from the connected client. /// /// # Arguments @@ -363,10 +405,64 @@ where match raw_request { Message::Binary(bin_msg) => Some(self.handle_binary(bin_msg).await), Message::Text(text_msg) => Some(self.handle_text(text_msg).await), + Message::Pong(msg) => { + self.handle_pong(msg).await; + None + } _ => None, } } + /// Send a ping to the connected client and return a tag identifying the ping. + async fn send_ping(&mut self) -> Result + where + S: AsyncRead + AsyncWrite + Unpin, + { + let tag: u64 = rand::thread_rng().gen(); + debug!("Got request to ping our connection: {}", tag); + self.inner + .send_websocket_message(Message::Ping(tag.to_be_bytes().to_vec())) + .await?; + Ok(tag) + } + + /// Handles the ping timeout by responding back to the handler that requested the ping. + async fn handle_ping_timeout(&mut self) { + debug!("Ping timeout expired!"); + if let Some((_tag, reply_tx)) = self.is_active_ping_pending_reply.take() { + if let Err(err) = reply_tx.send(IsActive::NotActive) { + warn!("Failed to respond back to the handler requesting the ping: {err:?}"); + } + } + } + + async fn handle_is_active_request( + &mut self, + reply_tx: IsActiveResultSender, + ) -> Result<(), WsError> + where + S: AsyncRead + AsyncWrite + Unpin, + { + if self.is_active_ping_pending_reply.is_some() { + warn!("Received request to ping the client, but a ping is already in progress!"); + if let Err(err) = reply_tx.send(IsActive::BusyPinging) { + warn!("Failed to respond back to the handler requesting the ping: {err:?}"); + } + return Ok(()); + } + + match self.send_ping().await { + Ok(tag) => { + self.is_active_ping_pending_reply = Some((tag, reply_tx)); + Ok(()) + } + Err(err) => { + warn!("Failed to send ping to client: {err}. Assuming the connection is dead."); + Err(err) + } + } + } + /// Simultaneously listens for incoming client requests, which realistically should only be /// binary requests to forward sphinx packets or increase bandwidth /// and for sphinx packets received from the mix network that should be sent back to the client. @@ -377,11 +473,32 @@ where { trace!("Started listening for ALL incoming requests..."); + // Ping timeout future used to check if the client responded to our ping request + let mut ping_timeout: OptionFuture<_> = None.into(); + while !shutdown.is_shutdown() { tokio::select! { _ = shutdown.recv() => { log::trace!("client_handling::AuthenticatedHandler: received shutdown"); - } + }, + // Received a request to ping the client to check if it's still active + tx = self.is_active_request_receiver.next() => { + match tx { + None => break, + Some(reply_tx) => { + if self.handle_is_active_request(reply_tx).await.is_err() { + break; + } + // NOTE: fuse here due to .is_terminated() check below + ping_timeout = Some(Box::pin(tokio::time::sleep(Duration::from_millis(1000)).fuse())).into(); + } + }; + }, + // The ping timeout expired, meaning the client didn't respond to our ping request + _ = &mut ping_timeout, if !ping_timeout.is_terminated() => { + ping_timeout = None.into(); + self.handle_ping_timeout().await; + }, socket_msg = self.inner.read_websocket_message() => { let socket_msg = match socket_msg { None => break, @@ -406,7 +523,13 @@ where } }, mix_messages = self.mix_receiver.next() => { - let mix_messages = mix_messages.expect("sender was unexpectedly closed! this shouldn't have ever happened!"); + let mix_messages = match mix_messages { + None => { + warn!("mix receiver was closed! Assuming the connection is dead."); + break; + } + Some(mix_messages) => mix_messages, + }; if let Err(err) = self.inner.push_packets_to_client(&self.client.shared_keys, mix_messages).await { warn!("failed to send the unwrapped sphinx packets back to the client - {err}, assuming the connection is dead"); break; diff --git a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs index f03cdc26f9..349cf4200b 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs @@ -1,33 +1,43 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::node::client_handling::active_clients::ActiveClientsStore; -use crate::node::client_handling::websocket::connection_handler::coconut::CoconutVerifier; -use crate::node::client_handling::websocket::connection_handler::{ - AuthenticatedHandler, ClientDetails, InitialAuthResult, SocketStream, +use futures::{ + channel::{mpsc, oneshot}, + SinkExt, StreamExt, }; -use crate::node::storage::error::StorageError; -use crate::node::storage::Storage; -use futures::{channel::mpsc, SinkExt, StreamExt}; use log::*; use nym_crypto::asymmetric::identity; use nym_gateway_requests::authentication::encrypted_address::{ EncryptedAddressBytes, EncryptedAddressConversionError, }; -use nym_gateway_requests::iv::{IVConversionError, IV}; -use nym_gateway_requests::registration::handshake::error::HandshakeError; -use nym_gateway_requests::registration::handshake::{gateway_handshake, SharedKeys}; -use nym_gateway_requests::types::{ClientControlRequest, ServerResponse}; -use nym_gateway_requests::{BinaryResponse, PROTOCOL_VERSION}; +use nym_gateway_requests::{ + iv::{IVConversionError, IV}, + registration::handshake::{error::HandshakeError, gateway_handshake, SharedKeys}, + types::{ClientControlRequest, ServerResponse}, + BinaryResponse, PROTOCOL_VERSION, +}; use nym_mixnet_client::forwarder::MixForwardingSender; use nym_sphinx::DestinationAddressBytes; use rand::{CryptoRng, Rng}; -use std::convert::TryFrom; -use std::sync::Arc; +use std::{convert::TryFrom, sync::Arc, time::Duration}; use thiserror::Error; use tokio::io::{AsyncRead, AsyncWrite}; use tokio_tungstenite::tungstenite::{protocol::Message, Error as WsError}; +use crate::node::{ + client_handling::{ + active_clients::ActiveClientsStore, + websocket::{ + connection_handler::{ + coconut::CoconutVerifier, AuthenticatedHandler, ClientDetails, InitialAuthResult, + SocketStream, + }, + message_receiver::{IsActive, IsActiveRequestSender}, + }, + }, + storage::{error::StorageError, Storage}, +}; + #[derive(Debug, Error)] pub(crate) enum InitialAuthenticationError { #[error("Internal gateway storage error")] @@ -394,6 +404,59 @@ where } } + async fn handle_duplicate_client( + &mut self, + address: DestinationAddressBytes, + mut is_active_request_tx: IsActiveRequestSender, + ) -> Result<(), InitialAuthenticationError> { + // Ask the other connection to ping if they are still active. + // Use a oneshot channel to return the result to us + let (ping_result_sender, ping_result_receiver) = oneshot::channel(); + log::debug!("Asking other connection handler to ping the connected client to see if it is still active"); + if let Err(err) = is_active_request_tx.send(ping_result_sender).await { + warn!("Failed to send ping request to other handler: {err}"); + } + + // Wait for the reply + match tokio::time::timeout(Duration::from_millis(2000), ping_result_receiver).await { + Ok(Ok(res)) => { + match res { + IsActive::NotActive => { + // The other handler reported that the client is not active, so we can + // disconnect the other client and continue with this connection. + log::debug!("Other handler reports it is not active"); + self.active_clients_store.disconnect(address); + } + IsActive::Active => { + // The other handled reported a positive reply, so we have to assume it's + // still active and disconnect this connection. + log::info!("Other handler reports it is active"); + return Err(InitialAuthenticationError::DuplicateConnection); + } + IsActive::BusyPinging => { + // The other handler is already busy pinging the client, so we have to + // assume it's still active and disconnect this connection. + log::debug!("Other handler reports it is already busy pinging the client"); + return Err(InitialAuthenticationError::DuplicateConnection); + } + } + } + Ok(Err(_)) => { + // Other channel failed to reply (the channel sender probably dropped) + log::info!("Other connection failed to reply, disconnecting it in favour of this new connection"); + self.active_clients_store.disconnect(address); + } + Err(_) => { + // Timeout waiting for reply + log::warn!( + "Other connection timed out, disconnecting it in favour of this new connection" + ); + self.active_clients_store.disconnect(address); + } + } + Ok(()) + } + /// Tries to handle the received authentication request by checking correctness of the received data. /// /// # Arguments @@ -418,8 +481,11 @@ where let encrypted_address = EncryptedAddressBytes::try_from_base58_string(enc_address)?; let iv = IV::try_from_base58_string(iv)?; - if self.active_clients_store.get(address).is_some() { - return Err(InitialAuthenticationError::DuplicateConnection); + // Check for duplicate clients + if let Some(client_tx) = self.active_clients_store.get(address) { + log::warn!("Detected duplicate connection for client: {}", address); + self.handle_duplicate_client(address, client_tx.is_active_request_sender) + .await?; } let shared_keys = self @@ -606,12 +672,19 @@ where } return if let Some(client_details) = auth_result.client_details { - self.active_clients_store - .insert(client_details.address, mix_sender); + // Channel for handlers to ask other handlers if they are still active. + let (is_active_request_sender, is_active_request_receiver) = + mpsc::unbounded(); + self.active_clients_store.insert( + client_details.address, + mix_sender, + is_active_request_sender, + ); Some(AuthenticatedHandler::upgrade( self, client_details, mix_receiver, + is_active_request_receiver, )) } else { None diff --git a/gateway/src/node/client_handling/websocket/connection_handler/mod.rs b/gateway/src/node/client_handling/websocket/connection_handler/mod.rs index ad6a0d03a1..ee7474f3a7 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/mod.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/mod.rs @@ -100,7 +100,7 @@ pub(crate) async fn handle_connection( .await { None => { - trace!("received shutdown signal while performing initial authetnication"); + trace!("received shutdown signal while performing initial authentication"); return; } Some(None) => { diff --git a/gateway/src/node/client_handling/websocket/message_receiver.rs b/gateway/src/node/client_handling/websocket/message_receiver.rs index 3ff265b2a7..fb41083803 100644 --- a/gateway/src/node/client_handling/websocket/message_receiver.rs +++ b/gateway/src/node/client_handling/websocket/message_receiver.rs @@ -1,7 +1,20 @@ // Copyright 2020 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use futures::channel::mpsc; +use futures::channel::{mpsc, oneshot}; pub(crate) type MixMessageSender = mpsc::UnboundedSender>>; pub(crate) type MixMessageReceiver = mpsc::UnboundedReceiver>>; + +// Channels used for one handler to requester another handler to check that the client is still +// active. The result is then passed back to the requesting handler in the oneshot channel. +pub(crate) type IsActiveRequestSender = mpsc::UnboundedSender; +pub(crate) type IsActiveRequestReceiver = mpsc::UnboundedReceiver; + +#[derive(Debug)] +pub(crate) enum IsActive { + Active, + NotActive, + BusyPinging, +} +pub(crate) type IsActiveResultSender = oneshot::Sender; diff --git a/gateway/src/node/mixnet_handling/receiver/connection_handler.rs b/gateway/src/node/mixnet_handling/receiver/connection_handler.rs index dd2bc5d402..e6071b8035 100644 --- a/gateway/src/node/mixnet_handling/receiver/connection_handler.rs +++ b/gateway/src/node/mixnet_handling/receiver/connection_handler.rs @@ -70,9 +70,9 @@ impl ConnectionHandler { } fn update_clients_store_cache_entry(&mut self, client_address: DestinationAddressBytes) { - if let Some(client_sender) = self.active_clients_store.get(client_address) { + if let Some(client_senders) = self.active_clients_store.get(client_address) { self.clients_store_cache - .insert(client_address, client_sender); + .insert(client_address, client_senders.mix_message_sender); } } diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index 91f99e9f81..9efff54500 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-mixnode" -version = "1.1.29" +version = "1.1.30" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index a6571adbd5..98b0c769dc 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -274,16 +274,19 @@ impl MixNode { let shutdown = TaskManager::default(); - let (node_stats_pointer, node_stats_update_sender) = - self.start_node_stats_controller(shutdown.subscribe()); - let delay_forwarding_channel = self - .start_packet_delay_forwarder(node_stats_update_sender.clone(), shutdown.subscribe()); + let (node_stats_pointer, node_stats_update_sender) = self + .start_node_stats_controller(shutdown.subscribe().named("node_statistics::Controller")); + let delay_forwarding_channel = self.start_packet_delay_forwarder( + node_stats_update_sender.clone(), + shutdown.subscribe().named("DelayForwarder"), + ); self.start_socket_listener( node_stats_update_sender, delay_forwarding_channel, - shutdown.subscribe(), + shutdown.subscribe().named("Listener"), ); - let atomic_verloc_results = self.start_verloc_measurements(shutdown.subscribe()); + let atomic_verloc_results = + self.start_verloc_measurements(shutdown.subscribe().named("VerlocMeasurer")); // Rocket handles shutdown on it's own, but its shutdown handling should be incorporated // with that of the rest of the tasks. diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 3fb1c48506..5f5f6a9bd6 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-api" -version = "1.1.29" +version = "1.1.30" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", diff --git a/nym-browser-extension/package.json b/nym-browser-extension/package.json index e9617eb933..08fdc6f39c 100644 --- a/nym-browser-extension/package.json +++ b/nym-browser-extension/package.json @@ -4,10 +4,8 @@ "main": "index.js", "license": "MIT", "scripts": { - "preinstall": "yarn build:wasm", "dev": "yarn webpack serve --config webpack.dev.js", "build": "yarn preinstall && webpack build --progress --config webpack.prod.js", - "build:wasm": "cd storage && make wasm-pack", "lint": "eslint src", "lint:fix": "eslint src --fix", "lint:ts": "tsc --noEmit", @@ -22,10 +20,10 @@ "@mui/material": "^5.11.15", "@mui/system": "^5.11.15", "@nymproject/mui-theme": "^1.0.0", - "@nymproject/nym-validator-client": "0.19.0", + "@nymproject/nym-validator-client": ">=1.2.0-rc.0 || 1", "@nymproject/react": "^1.0.0", "@nymproject/types": "^1.0.0", - "@nymproject/extension-storage": "file:./storage/pkg", + "@nymproject/extension-storage": ">=1.2.0-rc.0 || 1", "@storybook/react": "^6.5.16", "big.js": "^6.2.1", "crypto-js": "^4.1.1", diff --git a/nym-browser-extension/storage/Cargo.toml b/nym-browser-extension/storage/Cargo.toml index dc48a6e7ef..5d88f1a4a8 100644 --- a/nym-browser-extension/storage/Cargo.toml +++ b/nym-browser-extension/storage/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "extension-storage" -version = "0.1.0" +version = "1.2.0-rc.2" edition = "2021" license = "Apache-2.0" repository = "https://github.com/nymtech/nym" @@ -11,29 +11,22 @@ repository = "https://github.com/nymtech/nym" crate-type = ["cdylib", "rlib"] [dependencies] -bip39 = { version = "2.0.0", features = ["zeroize"] } -js-sys = "*" -serde-wasm-bindgen = "0.5" -thiserror = "1.0.40" -wasm-bindgen = { version = "*" } # , features = ["serde-serialize"] } -wasm-bindgen-futures = "*" -zeroize = "1.6.0" - +bip39 = { workspace = true } +js-sys = { workspace = true } +serde-wasm-bindgen = { workspace = true } +thiserror = { workspace = true } +wasm-bindgen = { workspace = true } +wasm-bindgen-futures = { workspace = true } +zeroize = { workspace = true } console_error_panic_hook = { version = "0.1", optional = true } -# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size -# compared to the default allocator's ~10K. It is slower than the default -# allocator, however. -# -# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. -wee_alloc = { version = "0.4", optional = true } - -wasm-utils = { path = "../../common/wasm-utils", features = ["storage"] } +wasm-utils = { path = "../../common/wasm/utils" } +wasm-storage = { path = "../../common/wasm/storage" } #[package.metadata.wasm-pack.profile.release] #wasm-opt = false [features] -default = ["console_error_panic_hook"] \ No newline at end of file +default = ["console_error_panic_hook"] diff --git a/nym-browser-extension/storage/Makefile b/nym-browser-extension/storage/Makefile index c7d6657cd6..c9cc632572 100644 --- a/nym-browser-extension/storage/Makefile +++ b/nym-browser-extension/storage/Makefile @@ -1,2 +1,2 @@ wasm-pack: - wasm-pack build --scope nymproject \ No newline at end of file + wasm-pack build --scope nymproject --out-dir ../../dist/wasm/extension-storage \ No newline at end of file diff --git a/nym-browser-extension/storage/src/error.rs b/nym-browser-extension/storage/src/error.rs index 2ea167fa21..6e3472ba73 100644 --- a/nym-browser-extension/storage/src/error.rs +++ b/nym-browser-extension/storage/src/error.rs @@ -1,10 +1,10 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use js_sys::Promise; use thiserror::Error; -use wasm_bindgen::JsValue; -use wasm_utils::simple_js_error; -use wasm_utils::storage::error::StorageError; +use wasm_storage::error::StorageError; +use wasm_utils::wasm_error; #[derive(Debug, Error)] pub enum ExtensionStorageError { @@ -30,8 +30,4 @@ pub enum ExtensionStorageError { }, } -impl From for JsValue { - fn from(value: ExtensionStorageError) -> Self { - simple_js_error(value.to_string()) - } -} +wasm_error!(ExtensionStorageError); diff --git a/nym-browser-extension/storage/src/lib.rs b/nym-browser-extension/storage/src/lib.rs index 9f4ae1302b..767755c0a3 100644 --- a/nym-browser-extension/storage/src/lib.rs +++ b/nym-browser-extension/storage/src/lib.rs @@ -1,14 +1,22 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use wasm_bindgen::prelude::*; - +#[cfg(target_arch = "wasm32")] pub mod error; + +#[cfg(target_arch = "wasm32")] pub mod storage; +#[cfg(target_arch = "wasm32")] pub use error::ExtensionStorageError; + +#[cfg(target_arch = "wasm32")] pub use storage::ExtensionStorage; +#[cfg(target_arch = "wasm32")] +use wasm_bindgen::prelude::*; + +#[cfg(target_arch = "wasm32")] #[wasm_bindgen] pub fn set_panic_hook() { // When the `console_error_panic_hook` feature is enabled, we can call the diff --git a/nym-browser-extension/storage/src/storage.rs b/nym-browser-extension/storage/src/storage.rs index 9b7278d028..4a0874f47e 100644 --- a/nym-browser-extension/storage/src/storage.rs +++ b/nym-browser-extension/storage/src/storage.rs @@ -6,8 +6,9 @@ use js_sys::Promise; use std::sync::Arc; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; -use wasm_utils::storage::{IdbVersionChangeEvent, WasmStorage}; -use wasm_utils::{check_promise_result, PromisableResult, PromisableResultError}; +use wasm_storage::{IdbVersionChangeEvent, WasmStorage}; +use wasm_utils::check_promise_result; +use wasm_utils::error::{PromisableResult, PromisableResultError}; use zeroize::Zeroizing; const STORAGE_NAME: &str = "nym-wallet-extension"; @@ -25,6 +26,7 @@ pub struct ExtensionStorage { inner: Arc, } +#[allow(clippy::type_complexity)] fn db_migration() -> Box Result<(), JsValue>> { Box::new(|evt: &IdbVersionChangeEvent| -> Result<(), JsValue> { // Even if the web-sys bindings expose the version as a f64, the IndexedDB API diff --git a/nym-connect/desktop/CHANGELOG.md b/nym-connect/desktop/CHANGELOG.md index 371cf6441e..29fcf45d6c 100644 --- a/nym-connect/desktop/CHANGELOG.md +++ b/nym-connect/desktop/CHANGELOG.md @@ -2,6 +2,12 @@ ## [Unreleased] +## [v1.1.21-kitkat] (2023-09-12) + +- NC - Handle failure when config is too old ([#3847]) + +[#3847]: https://github.com/nymtech/nym/issues/3847 + ## [v1.1.20-twix] (2023-09-05) - nym-connect directory error handling ([#3830]) diff --git a/nym-connect/desktop/Cargo.lock b/nym-connect/desktop/Cargo.lock index e7c60df056..9e3096872a 100644 --- a/nym-connect/desktop/Cargo.lock +++ b/nym-connect/desktop/Cargo.lock @@ -2577,6 +2577,27 @@ dependencies = [ "regex", ] +[[package]] +name = "gloo-net" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a66b4e3c7d9ed8d315fd6b97c8b1f74a7c6ecbbc2320e65ae7ed38b7068cc620" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "http", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "gloo-timers" version = "0.2.6" @@ -2589,6 +2610,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gloo-utils" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "gobject-sys" version = "0.15.10" @@ -3298,9 +3332,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -3992,7 +4026,7 @@ dependencies = [ [[package]] name = "nym-connect" -version = "1.1.19" +version = "1.1.20" dependencies = [ "anyhow", "bip39", @@ -4161,6 +4195,7 @@ version = "0.1.0" dependencies = [ "futures", "getrandom 0.2.10", + "gloo-utils", "log", "nym-bandwidth-controller", "nym-coconut-interface", @@ -4575,6 +4610,7 @@ dependencies = [ "nym-sphinx-routing", "nym-sphinx-types", "rand 0.7.3", + "semver 0.11.0", "thiserror", ] @@ -7874,9 +7910,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -7884,24 +7920,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.33" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" dependencies = [ "cfg-if", "js-sys", @@ -7911,9 +7947,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7921,22 +7957,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-streams" @@ -7957,6 +7993,8 @@ version = "0.1.0" dependencies = [ "futures", "getrandom 0.2.10", + "gloo-net", + "gloo-utils", "js-sys", "tungstenite", "wasm-bindgen", @@ -7980,9 +8018,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/nym-connect/desktop/package.json b/nym-connect/desktop/package.json index 00eececabe..8b147f6324 100644 --- a/nym-connect/desktop/package.json +++ b/nym-connect/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@nym/nym-connect", - "version": "1.1.20", + "version": "1.1.21", "main": "index.js", "license": "MIT", "scripts": { diff --git a/nym-connect/desktop/src-tauri/Cargo.toml b/nym-connect/desktop/src-tauri/Cargo.toml index 6b4de12a5f..3947434d65 100644 --- a/nym-connect/desktop/src-tauri/Cargo.toml +++ b/nym-connect/desktop/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-connect" -version = "1.1.20" +version = "1.1.21" description = "nym-connect" authors = ["Nym Technologies SA"] license = "" @@ -37,7 +37,8 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serde_repr = "0.1" tap = "1.0.1" -tauri = { version = "^1.2.2", features = ["clipboard-write-text", "macos-private-api", "notification-all", "shell-open", "system-tray", "updater", "window-close", "window-minimize", "window-start-dragging"] } +# 07.07.23: JS: I changed the version from ^1.2.2 to fix up indirect import of web-sys +tauri = { version = "1.4.1", features = ["clipboard-write-text", "macos-private-api", "notification-all", "shell-open", "system-tray", "updater", "window-close", "window-minimize", "window-start-dragging"] } #tendermint-rpc = "0.23.0" thiserror = "1.0" time = { version = "0.3.17", features = ["local-offset"] } diff --git a/nym-connect/desktop/src-tauri/src/config/mod.rs b/nym-connect/desktop/src-tauri/src/config/mod.rs index 538b5e5fbb..267c970069 100644 --- a/nym-connect/desktop/src-tauri/src/config/mod.rs +++ b/nym-connect/desktop/src-tauri/src/config/mod.rs @@ -8,6 +8,7 @@ use crate::error::{BackendError, Result}; use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails; use nym_client_core::client::key_manager::persistence::OnDiskKeys; use nym_client_core::config::GatewayEndpointConfig; +use nym_client_core::error::ClientCoreError; use nym_client_core::init::GatewaySetup; use nym_config::{ must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate, @@ -137,6 +138,17 @@ fn init_paths(id: &str) -> io::Result<()> { fs::create_dir_all(default_config_directory(id)) } +fn try_extract_version_for_upgrade_failure(err: BackendError) -> Option { + if let BackendError::ClientCoreError { + source: ClientCoreError::UnableToUpgradeConfigFile { new_version }, + } = err + { + Some(new_version) + } else { + None + } +} + pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: String) -> Result<()> { log::trace!("Initialising client..."); @@ -145,10 +157,29 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str let _validated = identity::PublicKey::from_base58_string(&chosen_gateway_id) .map_err(|_| BackendError::UnableToParseGateway)?; - let already_init = if default_config_filepath(&id).exists() { + let config_path = default_config_filepath(&id); + let already_init = if config_path.exists() { // in case we're using old config, try to upgrade it // (if we're using the current version, it's a no-op) - try_upgrade_config(&id)?; + if let Err(err) = try_upgrade_config(&id) { + log::error!( + "Failed to upgrade config file {}: {:?}", + config_path.display(), + err + ); + if let Some(failed_at_version) = try_extract_version_for_upgrade_failure(err) { + return Err( + BackendError::CouldNotUpgradeExistingConfigurationFileAtVersion { + file: config_path, + failed_at_version, + }, + ); + } else { + return Err(BackendError::CouldNotUpgradeExistingConfigurationFile { + file: config_path, + }); + } + }; eprintln!("SOCKS5 client \"{id}\" was already initialised before"); true } else { diff --git a/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_20_2.rs b/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_20_2.rs index df6356b226..0a2f017a75 100644 --- a/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_20_2.rs +++ b/nym-connect/desktop/src-tauri/src/config/old_config_v1_1_20_2.rs @@ -3,6 +3,7 @@ use crate::config::persistence::NymConnectPaths; use crate::config::{default_config_filepath, Config}; +use crate::error::Result; use nym_bin_common::logging::LoggingSettings; use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2; use nym_client_core::config::GatewayEndpointConfig; @@ -39,16 +40,16 @@ impl ConfigV1_1_20_2 { // in this upgrade, gateway endpoint configuration was moved out of the config file, // so its returned to be stored elsewhere. - pub fn upgrade(self) -> (Config, GatewayEndpointConfig) { + pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig)> { let gateway_details = self.core.base.client.gateway_endpoint.clone().into(); let config = Config { core: self.core.into(), storage_paths: NymConnectPaths { - common_paths: self.storage_paths.common_paths.upgrade_default(), + common_paths: self.storage_paths.common_paths.upgrade_default()?, }, // logging: self.logging, }; - (config, gateway_details) + Ok((config, gateway_details)) } } diff --git a/nym-connect/desktop/src-tauri/src/config/upgrade.rs b/nym-connect/desktop/src-tauri/src/config/upgrade.rs index 2f4d37b777..2f41a964f4 100644 --- a/nym-connect/desktop/src-tauri/src/config/upgrade.rs +++ b/nym-connect/desktop/src-tauri/src/config/upgrade.rs @@ -8,7 +8,7 @@ use crate::{ }, error::{BackendError, Result}, }; -use log::info; +use log::{debug, info}; use nym_client_core::{ client::{ base_client::storage::gateway_details::{OnDiskGatewayDetails, PersistedGatewayDetails}, @@ -52,7 +52,7 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result { let updated_step1: ConfigV1_1_20 = old_config.into(); let updated_step2: ConfigV1_1_20_2 = updated_step1.into(); - let (updated, gateway_config) = updated_step2.upgrade(); + let (updated, gateway_config) = updated_step2.upgrade()?; persist_gateway_details(&updated, gateway_config)?; updated.save_to_default_location()?; @@ -72,7 +72,7 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result { info!("It is going to get updated to the current specification."); let updated_step1: ConfigV1_1_20_2 = old_config.into(); - let (updated, gateway_config) = updated_step1.upgrade(); + let (updated, gateway_config) = updated_step1.upgrade()?; persist_gateway_details(&updated, gateway_config)?; updated.save_to_default_location()?; @@ -89,7 +89,7 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result { info!("It seems the client is using <= v1.1.20_2 config template."); info!("It is going to get updated to the current specification."); - let (updated, gateway_config) = old_config.upgrade(); + let (updated, gateway_config) = old_config.upgrade()?; persist_gateway_details(&updated, gateway_config)?; updated.save_to_default_location()?; @@ -97,6 +97,7 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result { } pub fn try_upgrade_config(id: &str) -> Result<()> { + debug!("Attempting to upgrade config file for \"{id}\""); if try_upgrade_v1_1_13_config(id)? { return Ok(()); } diff --git a/nym-connect/desktop/src-tauri/src/error.rs b/nym-connect/desktop/src-tauri/src/error.rs index a6290280c3..5b324a8850 100644 --- a/nym-connect/desktop/src-tauri/src/error.rs +++ b/nym-connect/desktop/src-tauri/src/error.rs @@ -81,6 +81,13 @@ pub enum BackendError { CouldNotGetConfigFilename, #[error("could not load existing gateway configuration")] CouldNotLoadExistingGatewayConfiguration(std::io::Error), + #[error("could not upgrade `{file}` to latest version")] + CouldNotUpgradeExistingConfigurationFile { file: std::path::PathBuf }, + #[error("could not upgrade `{file}` to latest version (failed at {failed_at_version})")] + CouldNotUpgradeExistingConfigurationFileAtVersion { + file: std::path::PathBuf, + failed_at_version: String, + }, #[error("no gateways found in directory")] NoGatewaysFoundInDirectory, diff --git a/nym-connect/desktop/src-tauri/tauri.conf.json b/nym-connect/desktop/src-tauri/tauri.conf.json index 46c8645e64..323b734069 100644 --- a/nym-connect/desktop/src-tauri/tauri.conf.json +++ b/nym-connect/desktop/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "package": { "productName": "nym-connect", - "version": "1.1.20" + "version": "1.1.21" }, "build": { "distDir": "../dist", @@ -51,7 +51,7 @@ "updater": { "active": true, "endpoints": [ - "https://nymtech.net/.wellknown/mainnet/connect/updater.json" + "https://nymtech.net/.wellknown/connect/updater.json" ], "dialog": true, "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IENCNzQ2M0E5N0VFODE2NApSV1JrZ2U2WE9rYTNETTg1OTBKdE5uWUEra0hML2syOVUvQ2lxZmFZRzZ1T3NWbGM0eVRzUTVhVwo=" diff --git a/nym-connect/desktop/src/context/main.tsx b/nym-connect/desktop/src/context/main.tsx index 2f553b5153..9e8f5f21af 100644 --- a/nym-connect/desktop/src/context/main.tsx +++ b/nym-connect/desktop/src/context/main.tsx @@ -36,8 +36,8 @@ export type TClientContext = { setConnectionStats: (connectionStats: ConnectionStatsItem[] | undefined) => void; setConnectedSince: (connectedSince: DateTime | undefined) => void; setShowInfoModal: (show: boolean) => void; - setServiceProvider: () => void; - setGateway: () => void; + setServiceProvider: () => Promise; + setGateway: () => Promise; startConnecting: () => Promise; startDisconnecting: () => Promise; setUserDefinedGateway: React.Dispatch>; @@ -239,6 +239,13 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { const setPrivacyLevel = async (value: PrivacyLevel) => { await invoke('set_privacy_level', { privacyLevel: value }); + // refresh service providers list + const fetchedServices = await invoke('get_services'); + setServiceProviders(fetchedServices); + // reset any previously selected SP + await invoke('set_selected_sp', { + serviceProvider: { is_active: false }, + }); // refresh user data await getUserData(); }; diff --git a/nym-connect/desktop/src/context/mocks/main.tsx b/nym-connect/desktop/src/context/mocks/main.tsx index 02de84aa69..2da2661939 100644 --- a/nym-connect/desktop/src/context/mocks/main.tsx +++ b/nym-connect/desktop/src/context/mocks/main.tsx @@ -21,8 +21,8 @@ const mockValues: TClientContext = { setConnectionStatus: () => {}, startConnecting: async () => {}, startDisconnecting: async () => {}, - setServiceProvider: () => {}, - setGateway: () => {}, + setServiceProvider: async () => {}, + setGateway: async () => {}, setUserDefinedGateway: () => {}, setUserDefinedSPAddress: () => {}, setMonitoring: async () => {}, diff --git a/nym-vpn/android/.gitignore b/nym-vpn/android/.gitignore new file mode 100644 index 0000000000..31caa0cedf --- /dev/null +++ b/nym-vpn/android/.gitignore @@ -0,0 +1,71 @@ +# Built application files +*.apk +*.aar +*.ap_ +*.aab +# Files for the ART/Dalvik VM +*.dex +# Java class files +*.class +# Generated files +bin/ +gen/ +out/ +release/ +build/ +# Gradle files +.gradle/ +# Local configuration file (sdk path, etc) +local.properties +# Proguard folder generated by Eclipse +proguard/ +# Log Files +*.log +# Android Studio Navigation editor temp files +.navigation/ +# Android Studio captures folder +captures/ +# IntelliJ +*.iml +.idea/ +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/gradle.xml +# .idea/assetWizardSettings.xml +# .idea/dictionaries +.idea/libraries +# Android Studio 3 in .gitignore file. +.idea/caches +.idea/modules.xml +# Comment next line if keeping position of elements in Navigation Editor is relevant for you +.idea/navEditor.xml +# Keystore files +# Uncomment the following lines if you do not want to check your keystore files in. +*.jks +*.keystore +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild +.cxx/ +# Freeline +freeline.py +freeline/ +freeline_project_description.json +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md +# Version control +vcs.xml +# lint +lint/intermediates/ +lint/generated/ +lint/outputs/ +lint/tmp/ +# lint/reports/ +# MacOS +.DS_Store +# App Specific cases +app/release/output.json +.idea/codeStyles/ diff --git a/nym-vpn/android/LICENSE b/nym-vpn/android/LICENSE new file mode 100644 index 0000000000..51f3844dba --- /dev/null +++ b/nym-vpn/android/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 NymConnect + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/nym-vpn/android/README.md b/nym-vpn/android/README.md new file mode 100644 index 0000000000..e4a334e993 --- /dev/null +++ b/nym-vpn/android/README.md @@ -0,0 +1,42 @@ +## NymConnect for Android + +### Prerequisites + +_TODO_ + +### Getting started + +[Install](https://developer.android.com/studio/install) Android Studio and open +the project.\ +Setup an android emulator using AVD.\ +[Run](https://developer.android.com/studio/run/emulator) the project. + +**⚠ NOTE**: be sure +to [set](https://developer.android.com/studio/run#changing-variant) +the build variant to `x86_64Debug` when running on emulator + +### Features + +* Add tunnels via .conf file +* Auto connect to VPN based on Wi-Fi SSID +* Split tunneling by application with search +* Always-on VPN for Android support +* Quick tile support for vpn toggling +* Dynamic shortcuts support for automation integration +* Configurable Trusted Network list +* Optional auto connect on mobile data +* Automatic service restart after reboot +* Service will stay running in background after app has been closed + +### Building + +_TODO_ + +### Credits + +This project is based on the "WG Tunnel" project made by Zane Schepke +https://github.com/zaneschepke/wgtunnel + +### License + +MIT diff --git a/nym-vpn/android/app/.gitignore b/nym-vpn/android/app/.gitignore new file mode 100644 index 0000000000..956c004dc0 --- /dev/null +++ b/nym-vpn/android/app/.gitignore @@ -0,0 +1,2 @@ +/build +/release \ No newline at end of file diff --git a/nym-vpn/android/app/build.gradle.kts b/nym-vpn/android/app/build.gradle.kts new file mode 100644 index 0000000000..bc158e58e9 --- /dev/null +++ b/nym-vpn/android/app/build.gradle.kts @@ -0,0 +1,159 @@ +val rExtra = rootProject.extra + +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") + kotlin("kapt") + id("com.google.dagger.hilt.android") + id("org.jetbrains.kotlin.plugin.serialization") + id("io.objectbox") +} + +android { + namespace = "net.nymtech.nymconnect" + compileSdk = 34 + + val versionMajor = 1 + val versionMinor = 0 + val versionPatch = 0 + val versionBuild = 0 + + defaultConfig { + applicationId = "net.nymtech.nymconnect" + minSdk = 28 + targetSdk = 34 + versionCode = versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild + versionName = "${versionMajor}.${versionMinor}.${versionPatch}" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + } + + buildTypes { + release { + isDebuggable = false + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = "17" + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.4.8" + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } + + /* flavorDimensions += "abi" + productFlavors { + create("universal") { + dimension = "abi" + ndk { + abiFilters += listOf("arm64-v8a", "armeabi-v7a", "x86_64", "x86") + } + } + create("arch64") { + dimension = "abi" + ndk { + abiFilters += listOf("arm64-v8a", "x86_64") + } + } + create("arm64") { + dimension = "abi" + ndk { + abiFilters += "arm64-v8a" + } + } + create("arm") { + dimension = "abi" + ndk { + abiFilters += "armeabi-v7a" + } + } + create("x86_64") { + dimension = "abi" + ndk { + abiFilters += "x86_64" + } + } + create("x86") { + dimension = "abi" + ndk { + abiFilters += "x86" + } + } + } */ +} + +dependencies { + implementation("androidx.core:core-ktx:1.10.1") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1") + implementation("androidx.activity:activity-compose:1.7.2") + implementation(platform("androidx.compose:compose-bom:2023.03.00")) + implementation("androidx.compose.ui:ui") + implementation("androidx.compose.ui:ui-graphics") + implementation("androidx.compose.ui:ui-tooling-preview") + implementation("androidx.compose.material3:material3:1.1.1") + implementation("androidx.appcompat:appcompat:1.6.1") + + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00")) + androidTestImplementation("androidx.compose.ui:ui-test-junit4") + debugImplementation("androidx.compose.ui:ui-tooling") + debugImplementation("androidx.compose.ui:ui-test-manifest") + + //wireguard tunnel + implementation("com.wireguard.android:tunnel:1.0.20230706") + + //logging + implementation("com.jakewharton.timber:timber:5.0.1") + + // compose navigation + implementation("androidx.navigation:navigation-compose:2.7.1") + implementation("androidx.hilt:hilt-navigation-compose:1.0.0") + + // hilt + implementation("com.google.dagger:hilt-android:${rExtra.get("hiltVersion")}") + kapt("com.google.dagger:hilt-android-compiler:${rExtra.get("hiltVersion")}") + + //accompanist + implementation("com.google.accompanist:accompanist-systemuicontroller:${rExtra.get("accompanistVersion")}") + implementation("com.google.accompanist:accompanist-permissions:${rExtra.get("accompanistVersion")}") + implementation("com.google.accompanist:accompanist-flowlayout:${rExtra.get("accompanistVersion")}") + implementation("com.google.accompanist:accompanist-navigation-animation:${rExtra.get("accompanistVersion")}") + implementation("com.google.accompanist:accompanist-drawablepainter:${rExtra.get("accompanistVersion")}") + + //db + implementation("io.objectbox:objectbox-kotlin:${rExtra.get("objectBoxVersion")}") + + //lifecycle + implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.1") + + //icons + implementation("androidx.compose.material:material-icons-extended:1.5.0") + + + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1") +} + +kapt { + correctErrorTypes = true +} \ No newline at end of file diff --git a/nym-vpn/android/app/objectbox-models/default.json b/nym-vpn/android/app/objectbox-models/default.json new file mode 100644 index 0000000000..dd7a8ab78e --- /dev/null +++ b/nym-vpn/android/app/objectbox-models/default.json @@ -0,0 +1,99 @@ +{ + "_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.", + "_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.", + "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", + "entities": [ + { + "id": "1:2692736974585027589", + "lastPropertyId": "15:5057486545428188436", + "name": "TunnelConfig", + "properties": [ + { + "id": "1:1985347930017457084", + "name": "id", + "type": 6, + "flags": 1 + }, + { + "id": "12:2409068226744965585", + "name": "name", + "indexId": "1:4811206443952699137", + "type": 9, + "flags": 34848 + }, + { + "id": "13:8987443291286312275", + "name": "wgQuick", + "type": 9 + } + ], + "relations": [] + }, + { + "id": "2:8887605597748372702", + "lastPropertyId": "9:4468844863383145378", + "name": "Settings", + "properties": [ + { + "id": "1:7485739868216068651", + "name": "id", + "type": 6, + "flags": 1 + }, + { + "id": "2:5814013113141456749", + "name": "isAutoTunnelEnabled", + "type": 1 + }, + { + "id": "4:5645665441196906014", + "name": "trustedNetworkSSIDs", + "type": 30 + }, + { + "id": "5:4989886999117763881", + "name": "isTunnelOnMobileDataEnabled", + "type": 1 + }, + { + "id": "6:3370284381040192129", + "name": "defaultTunnel", + "type": 9 + }, + { + "id": "9:4468844863383145378", + "name": "isAlwaysOnVpnEnabled", + "type": 1 + } + ], + "relations": [] + } + ], + "lastEntityId": "2:8887605597748372702", + "lastIndexId": "1:4811206443952699137", + "lastRelationId": "0:0", + "lastSequenceId": "0:0", + "modelVersion": 5, + "modelVersionParserMinimum": 5, + "retiredEntityUids": [], + "retiredIndexUids": [], + "retiredPropertyUids": [ + 1763475292291320186, + 6483820955437198310, + 8323071516033820771, + 5904440563612311217, + 1408037976996390989, + 7737847485212546994, + 8215616901775229364, + 8021610768066328637, + 6174306582797008721, + 2175939938544485767, + 7555225587864607050, + 969146862000617878, + 5057486545428188436, + 2814640993034665120, + 4981008812459251156 + ], + "retiredRelationUids": [], + "version": 1 +} \ No newline at end of file diff --git a/nym-vpn/android/app/objectbox-models/default.json.bak b/nym-vpn/android/app/objectbox-models/default.json.bak new file mode 100644 index 0000000000..d4084866ef --- /dev/null +++ b/nym-vpn/android/app/objectbox-models/default.json.bak @@ -0,0 +1,94 @@ +{ + "_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.", + "_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.", + "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", + "entities": [ + { + "id": "1:2692736974585027589", + "lastPropertyId": "15:5057486545428188436", + "name": "TunnelConfig", + "properties": [ + { + "id": "1:1985347930017457084", + "name": "id", + "type": 6, + "flags": 1 + }, + { + "id": "12:2409068226744965585", + "name": "name", + "indexId": "1:4811206443952699137", + "type": 9, + "flags": 34848 + }, + { + "id": "13:8987443291286312275", + "name": "wgQuick", + "type": 9 + } + ], + "relations": [] + }, + { + "id": "2:8887605597748372702", + "lastPropertyId": "8:4981008812459251156", + "name": "Settings", + "properties": [ + { + "id": "1:7485739868216068651", + "name": "id", + "type": 6, + "flags": 1 + }, + { + "id": "2:5814013113141456749", + "name": "isAutoTunnelEnabled", + "type": 1 + }, + { + "id": "4:5645665441196906014", + "name": "trustedNetworkSSIDs", + "type": 30 + }, + { + "id": "5:4989886999117763881", + "name": "isTunnelOnMobileDataEnabled", + "type": 1 + }, + { + "id": "6:3370284381040192129", + "name": "defaultTunnel", + "type": 9 + } + ], + "relations": [] + } + ], + "lastEntityId": "2:8887605597748372702", + "lastIndexId": "1:4811206443952699137", + "lastRelationId": "0:0", + "lastSequenceId": "0:0", + "modelVersion": 5, + "modelVersionParserMinimum": 5, + "retiredEntityUids": [], + "retiredIndexUids": [], + "retiredPropertyUids": [ + 1763475292291320186, + 6483820955437198310, + 8323071516033820771, + 5904440563612311217, + 1408037976996390989, + 7737847485212546994, + 8215616901775229364, + 8021610768066328637, + 6174306582797008721, + 2175939938544485767, + 7555225587864607050, + 969146862000617878, + 5057486545428188436, + 2814640993034665120, + 4981008812459251156 + ], + "retiredRelationUids": [], + "version": 1 +} \ No newline at end of file diff --git a/nym-vpn/android/app/proguard-rules.pro b/nym-vpn/android/app/proguard-rules.pro new file mode 100644 index 0000000000..481bb43481 --- /dev/null +++ b/nym-vpn/android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/nym-vpn/android/app/src/androidTest/java/com/zaneschepke/wireguardautotunnel/ExampleInstrumentedTest.kt b/nym-vpn/android/app/src/androidTest/java/com/zaneschepke/wireguardautotunnel/ExampleInstrumentedTest.kt new file mode 100644 index 0000000000..c006861187 --- /dev/null +++ b/nym-vpn/android/app/src/androidTest/java/com/zaneschepke/wireguardautotunnel/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package net.nymtech.nymconnect + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("net.nymtech.nymconnect", appContext.packageName) + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/AndroidManifest.xml b/nym-vpn/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..391dff34b2 --- /dev/null +++ b/nym-vpn/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/ic_launcher-playstore.png b/nym-vpn/android/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000000..e5d8e99564 Binary files /dev/null and b/nym-vpn/android/app/src/main/ic_launcher-playstore.png differ diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/Constants.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/Constants.kt new file mode 100644 index 0000000000..c34ccaa493 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/Constants.kt @@ -0,0 +1,6 @@ +package net.nymtech.nymconnect + +object Constants { + const val VPN_CONNECTIVITY_CHECK_INTERVAL = 3000L; + const val VPN_STATISTIC_CHECK_INTERVAL = 10000L; +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt new file mode 100644 index 0000000000..f0d53e5162 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt @@ -0,0 +1,27 @@ +package net.nymtech.nymconnect + +import android.app.Application +import android.content.Context +import android.content.pm.PackageManager +import net.nymtech.nymconnect.repository.Repository +import net.nymtech.nymconnect.service.tunnel.model.Settings +import dagger.hilt.android.HiltAndroidApp +import javax.inject.Inject + +@HiltAndroidApp +class WireGuardAutoTunnel : Application() { + + @Inject + lateinit var settingsRepo : Repository + + override fun onCreate() { + super.onCreate() + settingsRepo.init() + } + + companion object { + fun isRunningOnAndroidTv(context : Context) : Boolean { + return context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK) + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/BoxModule.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/BoxModule.kt new file mode 100644 index 0000000000..032232369b --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/BoxModule.kt @@ -0,0 +1,40 @@ +package net.nymtech.nymconnect.module + +import android.content.Context +import net.nymtech.nymconnect.service.tunnel.model.MyObjectBox +import net.nymtech.nymconnect.service.tunnel.model.Settings +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import io.objectbox.Box +import io.objectbox.BoxStore +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +class BoxModule { + + @Provides + @Singleton + fun provideBoxStore(@ApplicationContext context : Context) : BoxStore { + return MyObjectBox.builder() + .androidContext(context.applicationContext) + .build() + } + + @Provides + @Singleton + fun provideBoxForSettings(store : BoxStore) : Box { + return store.boxFor(Settings::class.java) + } + + @Provides + @Singleton + fun provideBoxForTunnels(store : BoxStore) : Box { + return store.boxFor(TunnelConfig::class.java) + } + +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/RepositoryModule.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/RepositoryModule.kt new file mode 100644 index 0000000000..e402249cba --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/RepositoryModule.kt @@ -0,0 +1,25 @@ +package net.nymtech.nymconnect.module + +import net.nymtech.nymconnect.repository.Repository +import net.nymtech.nymconnect.repository.SettingsBox +import net.nymtech.nymconnect.repository.TunnelBox +import net.nymtech.nymconnect.service.tunnel.model.Settings +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +abstract class RepositoryModule { + + @Binds + @Singleton + abstract fun provideSettingsRepository(settingsBox: SettingsBox) : Repository + + @Binds + @Singleton + abstract fun provideTunnelRepository(tunnelBox: TunnelBox) : Repository +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/ServiceModule.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/ServiceModule.kt new file mode 100644 index 0000000000..fa043ec549 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/ServiceModule.kt @@ -0,0 +1,29 @@ +package net.nymtech.nymconnect.module + +import net.nymtech.nymconnect.service.network.MobileDataService +import net.nymtech.nymconnect.service.network.NetworkService +import net.nymtech.nymconnect.service.network.WifiService +import net.nymtech.nymconnect.service.notification.NotificationService +import net.nymtech.nymconnect.service.notification.WireGuardNotification +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.android.components.ServiceComponent +import dagger.hilt.android.scopes.ServiceScoped + +@Module +@InstallIn(ServiceComponent::class) +abstract class ServiceModule { + + @Binds + @ServiceScoped + abstract fun provideNotificationService(wireGuardNotification: WireGuardNotification) : NotificationService + + @Binds + @ServiceScoped + abstract fun provideWifiService(wifiService: WifiService) : NetworkService + + @Binds + @ServiceScoped + abstract fun provideMobileDataService(mobileDataService : MobileDataService) : NetworkService +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/TunnelModule.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/TunnelModule.kt new file mode 100644 index 0000000000..b5962a39d9 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/TunnelModule.kt @@ -0,0 +1,31 @@ +package net.nymtech.nymconnect.module + +import android.content.Context +import com.wireguard.android.backend.Backend +import com.wireguard.android.backend.GoBackend +import net.nymtech.nymconnect.service.tunnel.VpnService +import net.nymtech.nymconnect.service.tunnel.WireGuardTunnel +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +class TunnelModule { + + @Provides + @Singleton + fun provideBackend(@ApplicationContext context : Context) : Backend { + return GoBackend(context) + } + + @Provides + @Singleton + fun provideVpnService(backend: Backend) : VpnService { + return WireGuardTunnel(backend) + } + +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/BootReceiver.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/BootReceiver.kt new file mode 100644 index 0000000000..8fcf823c4f --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/BootReceiver.kt @@ -0,0 +1,39 @@ +package net.nymtech.nymconnect.receiver + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import net.nymtech.nymconnect.repository.Repository +import net.nymtech.nymconnect.service.foreground.ServiceManager +import net.nymtech.nymconnect.service.tunnel.model.Settings +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.cancel +import kotlinx.coroutines.launch +import javax.inject.Inject + +@AndroidEntryPoint +class BootReceiver : BroadcastReceiver() { + + @Inject + lateinit var settingsRepo : Repository + + override fun onReceive(context: Context, intent: Intent) { + if (intent.action == Intent.ACTION_BOOT_COMPLETED) { + CoroutineScope(Dispatchers.IO).launch { + try { + val settings = settingsRepo.getAll() + if (!settings.isNullOrEmpty()) { + val setting = settings.first() + if (setting.isAutoTunnelEnabled && setting.defaultTunnel != null) { + ServiceManager.startWatcherService(context, setting.defaultTunnel!!) + } + } + } finally { + cancel() + } + } + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt new file mode 100644 index 0000000000..97033a8f63 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt @@ -0,0 +1,39 @@ +package net.nymtech.nymconnect.receiver + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import net.nymtech.nymconnect.repository.Repository +import net.nymtech.nymconnect.service.foreground.ServiceManager +import net.nymtech.nymconnect.service.tunnel.model.Settings +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.cancel +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import javax.inject.Inject + +@AndroidEntryPoint +class NotificationActionReceiver : BroadcastReceiver() { + + @Inject + lateinit var settingsRepo : Repository + override fun onReceive(context: Context, intent: Intent?) { + CoroutineScope(Dispatchers.IO).launch { + try { + val settings = settingsRepo.getAll() + if (!settings.isNullOrEmpty()) { + val setting = settings.first() + if (setting.defaultTunnel != null) { + ServiceManager.stopVpnService(context) + delay(1000) + ServiceManager.startVpnService(context, setting.defaultTunnel.toString()) + } + } + } finally { + cancel() + } + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/Repository.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/Repository.kt new file mode 100644 index 0000000000..187957132c --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/Repository.kt @@ -0,0 +1,16 @@ +package net.nymtech.nymconnect.repository + +import kotlinx.coroutines.flow.Flow + +interface Repository { + suspend fun save(t : T) + suspend fun saveAll(t : List) + suspend fun getById(id : Long) : T? + suspend fun getAll() : List? + suspend fun delete(t : T) : Boolean? + suspend fun count() : Long? + + val itemFlow : Flow> + + fun init() +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/SettingsBox.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/SettingsBox.kt new file mode 100644 index 0000000000..f56247463c --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/SettingsBox.kt @@ -0,0 +1,63 @@ +package net.nymtech.nymconnect.repository + +import net.nymtech.nymconnect.service.tunnel.model.Settings +import io.objectbox.Box +import io.objectbox.BoxStore +import io.objectbox.kotlin.awaitCallInTx +import io.objectbox.kotlin.toFlow +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.launch +import javax.inject.Inject + + +class SettingsBox @Inject constructor(private val box : Box, private val boxStore : BoxStore) : Repository { + + @OptIn(ExperimentalCoroutinesApi::class) + override val itemFlow = box.query().build().subscribe().toFlow() + + override fun init() { + CoroutineScope(Dispatchers.IO).launch { + if(getAll().isNullOrEmpty()) { + save(Settings()) + } + } + } + + override suspend fun save(t : Settings) { + boxStore.awaitCallInTx { + box.put(t) + } + } + + override suspend fun saveAll(t : List) { + boxStore.awaitCallInTx { + box.put(t) + } + } + + override suspend fun getById(id: Long): Settings? { + return boxStore.awaitCallInTx { + box[id] + } + } + + override suspend fun getAll(): List? { + return boxStore.awaitCallInTx { + box.all + } + } + + override suspend fun delete(t : Settings): Boolean? { + return boxStore.awaitCallInTx { + box.remove(t) + } + } + + override suspend fun count() : Long? { + return boxStore.awaitCallInTx { + box.count() + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/TunnelBox.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/TunnelBox.kt new file mode 100644 index 0000000000..c57621d53c --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/TunnelBox.kt @@ -0,0 +1,57 @@ +package net.nymtech.nymconnect.repository + +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig +import io.objectbox.Box +import io.objectbox.BoxStore +import io.objectbox.kotlin.awaitCallInTx +import io.objectbox.kotlin.toFlow +import kotlinx.coroutines.ExperimentalCoroutinesApi +import timber.log.Timber +import javax.inject.Inject + +class TunnelBox @Inject constructor(private val box : Box,private val boxStore : BoxStore) : Repository { + + @OptIn(ExperimentalCoroutinesApi::class) + override val itemFlow = box.query().build().subscribe().toFlow() + override fun init() { + + } + + override suspend fun save(t : TunnelConfig) { + Timber.d("Saving tunnel config") + boxStore.awaitCallInTx { + box.put(t) + } + + } + + override suspend fun saveAll(t : List) { + boxStore.awaitCallInTx { + box.put(t) + } + } + + override suspend fun getById(id: Long): TunnelConfig? { + return boxStore.awaitCallInTx { + box[id] + } + } + + override suspend fun getAll(): List? { + return boxStore.awaitCallInTx { + box.all + } + } + + override suspend fun delete(t : TunnelConfig): Boolean? { + return boxStore.awaitCallInTx { + box.remove(t) + } + } + + override suspend fun count() : Long? { + return boxStore.awaitCallInTx { + box.count() + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/Action.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/Action.kt new file mode 100644 index 0000000000..ba4f930b12 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/Action.kt @@ -0,0 +1,6 @@ +package net.nymtech.nymconnect.service.foreground + +enum class Action { + START, + STOP +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ForegroundService.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ForegroundService.kt new file mode 100644 index 0000000000..9aaf0b93d8 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ForegroundService.kt @@ -0,0 +1,64 @@ +package net.nymtech.nymconnect.service.foreground + +import android.app.Service +import android.content.Intent +import android.os.Bundle +import android.os.IBinder +import timber.log.Timber + + +open class ForegroundService : Service() { + + private var isServiceStarted = false + + override fun onBind(intent: Intent): IBinder? { + // We don't provide binding, so return null + return null + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + Timber.d("onStartCommand executed with startId: $startId") + if (intent != null) { + val action = intent.action + Timber.d("using an intent with action $action") + when (action) { + Action.START.name -> startService(intent.extras) + Action.STOP.name -> stopService(intent.extras) + "android.net.VpnService" -> { + Timber.d("Always-on VPN starting service") + startService(intent.extras) + } + else -> Timber.d("This should never happen. No action in the received intent") + } + } else { + Timber.d( + "with a null intent. It has been probably restarted by the system." + ) + } + // by returning this we make sure the service is restarted if the system kills the service + return START_STICKY + } + + + override fun onDestroy() { + super.onDestroy() + Timber.d("The service has been destroyed") + } + + protected open fun startService(extras : Bundle?) { + if (isServiceStarted) return + Timber.d("Starting ${this.javaClass.simpleName}") + isServiceStarted = true + } + + protected open fun stopService(extras : Bundle?) { + Timber.d("Stopping ${this.javaClass.simpleName}") + try { + stopForeground(STOP_FOREGROUND_REMOVE) + stopSelf() + } catch (e: Exception) { + Timber.d("Service stopped without being started: ${e.message}") + } + isServiceStarted = false + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt new file mode 100644 index 0000000000..c00a796453 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt @@ -0,0 +1,90 @@ +package net.nymtech.nymconnect.service.foreground + +import android.app.ActivityManager +import android.app.Application +import android.app.Service +import android.content.Context +import android.content.Context.ACTIVITY_SERVICE +import android.content.Intent +import net.nymtech.nymconnect.R +import timber.log.Timber + +object ServiceManager { + @Suppress("DEPRECATION") + private // Deprecated for third party Services. + fun Context.isServiceRunning(service: Class) = + (getSystemService(ACTIVITY_SERVICE) as ActivityManager) + .getRunningServices(Integer.MAX_VALUE) + .any { it.service.className == service.name } + + fun getServiceState(context: Context, cls : Class): ServiceState { + val isServiceRunning = context.isServiceRunning(cls) + return if(isServiceRunning) ServiceState.STARTED else ServiceState.STOPPED + } + + private fun actionOnService(action: Action, context: Context, cls : Class, extras : Map? = null) { + if (getServiceState(context, cls) == ServiceState.STOPPED && action == Action.STOP) return + if (getServiceState(context, cls) == ServiceState.STARTED && action == Action.START) return + val intent = Intent(context, cls).also { + it.action = action.name + extras?.forEach {(k, v) -> + it.putExtra(k, v) + } + } + intent.component?.javaClass + try { + when(action) { + Action.START -> { + try { + context.startForegroundService(intent) + } catch (e : Exception) { + Timber.e("Unable to start service foreground ${e.message}") + context.startService(intent) + } + } + Action.STOP -> context.startService(intent) + } + } catch (e : Exception) { + Timber.tag("ServiceManager").e(e) + } + } + + fun startVpnService(context : Context, tunnelConfig : String) { + actionOnService( + Action.START, + context, + WireGuardTunnelService::class.java, + mapOf(context.getString(R.string.tunnel_extras_key) to tunnelConfig)) + } + fun stopVpnService(context : Context) { + actionOnService( + Action.STOP, + context, + WireGuardTunnelService::class.java + ) + } + + fun startWatcherService(context : Context, tunnelConfig : String) { + actionOnService( + Action.START, context, + WireGuardConnectivityWatcherService::class.java, mapOf(context. + getString(R.string.tunnel_extras_key) to + tunnelConfig)) + } + + fun stopWatcherService(context : Context) { + actionOnService( + Action.STOP, context, + WireGuardConnectivityWatcherService::class.java) + } + + fun toggleWatcherService(context: Context, tunnelConfig : String) { + when(getServiceState( + context, + WireGuardConnectivityWatcherService::class.java, + )) { + ServiceState.STARTED -> stopWatcherService(context) + ServiceState.STOPPED -> startWatcherService(context, tunnelConfig) + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceState.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceState.kt new file mode 100644 index 0000000000..9c26fa0795 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceState.kt @@ -0,0 +1,6 @@ +package net.nymtech.nymconnect.service.foreground + +enum class ServiceState { + STARTED, + STOPPED, +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardConnectivityWatcherService.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardConnectivityWatcherService.kt new file mode 100644 index 0000000000..fcfa811ea2 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardConnectivityWatcherService.kt @@ -0,0 +1,210 @@ +package net.nymtech.nymconnect.service.foreground + +import android.app.AlarmManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.os.PowerManager +import android.os.SystemClock +import com.wireguard.android.backend.Tunnel +import net.nymtech.nymconnect.Constants +import net.nymtech.nymconnect.R +import net.nymtech.nymconnect.repository.Repository +import net.nymtech.nymconnect.service.network.MobileDataService +import net.nymtech.nymconnect.service.network.NetworkService +import net.nymtech.nymconnect.service.network.NetworkStatus +import net.nymtech.nymconnect.service.network.WifiService +import net.nymtech.nymconnect.service.notification.NotificationService +import net.nymtech.nymconnect.service.tunnel.VpnService +import net.nymtech.nymconnect.service.tunnel.model.Settings +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import timber.log.Timber +import javax.inject.Inject + +@AndroidEntryPoint +class WireGuardConnectivityWatcherService : ForegroundService() { + + private val foregroundId = 122; + + @Inject + lateinit var wifiService : NetworkService + + @Inject + lateinit var mobileDataService : NetworkService + + @Inject + lateinit var settingsRepo: Repository + + @Inject + lateinit var notificationService : NotificationService + + @Inject + lateinit var vpnService : VpnService + + private var isWifiConnected = false; + private var isMobileDataConnected = false; + private var currentNetworkSSID = ""; + + private lateinit var watcherJob : Job; + private lateinit var setting : Settings + private lateinit var tunnelConfig: String + + private var wakeLock: PowerManager.WakeLock? = null + private val tag = this.javaClass.name; + + + override fun startService(extras: Bundle?) { + super.startService(extras) + val tunnelId = extras?.getString(getString(R.string.tunnel_extras_key)) + if (tunnelId != null) { + this.tunnelConfig = tunnelId + } + // we need this lock so our service gets not affected by Doze Mode + initWakeLock() + cancelWatcherJob() + launchWatcherNotification() + if(this::tunnelConfig.isInitialized) { + startWatcherJob() + } else { + stopService(extras) + } + } + + override fun stopService(extras: Bundle?) { + super.stopService(extras) + wakeLock?.let { + if (it.isHeld) { + it.release() + } + } + cancelWatcherJob() + stopSelf() + } + + private fun launchWatcherNotification() { + val notification = notificationService.createNotification( + channelId = getString(R.string.watcher_channel_id), + channelName = getString(R.string.watcher_channel_name), + description = getString(R.string.watcher_notification_text)) + super.startForeground(foregroundId, notification) + } + + //try to start task again if killed + override fun onTaskRemoved(rootIntent: Intent) { + Timber.d("Task Removed called") + val restartServiceIntent = Intent(rootIntent) + val restartServicePendingIntent: PendingIntent = PendingIntent.getService(this, 1, restartServiceIntent, + PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE); + applicationContext.getSystemService(Context.ALARM_SERVICE); + val alarmService: AlarmManager = applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager; + alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000, restartServicePendingIntent); + } + + private fun initWakeLock() { + wakeLock = + (getSystemService(Context.POWER_SERVICE) as PowerManager).run { + newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "$tag::lock").apply { + acquire() + } + } + } + + private fun cancelWatcherJob() { + if(this::watcherJob.isInitialized) { + watcherJob.cancel() + } + } + + private fun startWatcherJob() { + watcherJob = CoroutineScope(Dispatchers.IO).launch { + val settings = settingsRepo.getAll(); + if(!settings.isNullOrEmpty()) { + setting = settings[0] + } + launch { + watchForWifiConnectivityChanges() + } + if(setting.isTunnelOnMobileDataEnabled) { + launch { + watchForMobileDataConnectivityChanges() + } + } + launch { + manageVpn() + } + } + } + + private suspend fun watchForMobileDataConnectivityChanges() { + mobileDataService.networkStatus.collect { + when(it) { + is NetworkStatus.Available -> { + Timber.d("Gained Mobile data connection") + isMobileDataConnected = true + } + is NetworkStatus.CapabilitiesChanged -> { + isMobileDataConnected = true + Timber.d("Mobile data capabilities changed") + } + is NetworkStatus.Unavailable -> { + isMobileDataConnected = false + Timber.d("Lost mobile data connection") + } + + else -> {} + } + } + } + + private suspend fun watchForWifiConnectivityChanges() { + wifiService.networkStatus.collect { + when (it) { + is NetworkStatus.Available -> { + Timber.d("Gained Wi-Fi connection") + isWifiConnected = true + } + is NetworkStatus.CapabilitiesChanged -> { + Timber.d("Wifi capabilities changed") + isWifiConnected = true + currentNetworkSSID = wifiService.getNetworkName(it.networkCapabilities) ?: ""; + } + is NetworkStatus.Unavailable -> { + isWifiConnected = false + Timber.d("Lost Wi-Fi connection") + } + + else -> {} + } + } + } + + private suspend fun manageVpn() { + while(watcherJob.isActive) { + if(setting.isTunnelOnMobileDataEnabled && + !isWifiConnected && + isMobileDataConnected + && vpnService.getState() == Tunnel.State.DOWN) { + ServiceManager.startVpnService(this, tunnelConfig) + } else if(!setting.isTunnelOnMobileDataEnabled && + !isWifiConnected && + vpnService.getState() == Tunnel.State.UP) { + ServiceManager.stopVpnService(this) + } else if(isWifiConnected && + !setting.trustedNetworkSSIDs.contains(currentNetworkSSID) && + (vpnService.getState() != Tunnel.State.UP)) { + ServiceManager.startVpnService(this, tunnelConfig) + } else if((isWifiConnected && + setting.trustedNetworkSSIDs.contains(currentNetworkSSID)) && + (vpnService.getState() == Tunnel.State.UP)) { + ServiceManager.stopVpnService(this) + } + delay(Constants.VPN_CONNECTIVITY_CHECK_INTERVAL) + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardTunnelService.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardTunnelService.kt new file mode 100644 index 0000000000..776928e649 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardTunnelService.kt @@ -0,0 +1,154 @@ +package net.nymtech.nymconnect.service.foreground + +import android.app.PendingIntent +import android.content.Intent +import android.os.Bundle +import net.nymtech.nymconnect.R +import net.nymtech.nymconnect.receiver.NotificationActionReceiver +import net.nymtech.nymconnect.repository.Repository +import net.nymtech.nymconnect.service.notification.NotificationService +import net.nymtech.nymconnect.service.tunnel.HandshakeStatus +import net.nymtech.nymconnect.service.tunnel.VpnService +import net.nymtech.nymconnect.service.tunnel.model.Settings +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import timber.log.Timber +import javax.inject.Inject + +@AndroidEntryPoint +class WireGuardTunnelService : ForegroundService() { + + private val foregroundId = 123; + + @Inject + lateinit var vpnService : VpnService + + @Inject + lateinit var settingsRepo: Repository + + @Inject + lateinit var notificationService : NotificationService + + private lateinit var job : Job + + private var tunnelName : String = "" + + override fun startService(extras : Bundle?) { + super.startService(extras) + val tunnelConfigString = extras?.getString(getString(R.string.tunnel_extras_key)) + cancelJob() + job = CoroutineScope(Dispatchers.IO).launch { + if(tunnelConfigString != null) { + try { + val tunnelConfig = TunnelConfig.from(tunnelConfigString) + tunnelName = tunnelConfig.name + vpnService.startTunnel(tunnelConfig) + launchVpnStartingNotification() + } catch (e : Exception) { + Timber.e("Problem starting tunnel: ${e.message}") + stopService(extras) + } + } else { + Timber.d("Tunnel config null, starting default tunnel") + val settings = settingsRepo.getAll(); + if(!settings.isNullOrEmpty()) { + val setting = settings[0] + if(setting.defaultTunnel != null && setting.isAlwaysOnVpnEnabled) { + val tunnelConfig = TunnelConfig.from(setting.defaultTunnel!!) + tunnelName = tunnelConfig.name + vpnService.startTunnel(tunnelConfig) + launchVpnStartingNotification() + } + } + } + } + CoroutineScope(job).launch { + var didShowConnected = false + var didShowFailedHandshakeNotification = false + vpnService.handshakeStatus.collect { + when(it) { + HandshakeStatus.NOT_STARTED -> { + } + HandshakeStatus.NEVER_CONNECTED -> { + if(!didShowFailedHandshakeNotification) { + launchVpnConnectionFailedNotification(getString(R.string.initial_connection_failure_message)) + didShowFailedHandshakeNotification = true + didShowConnected = false + } + } + HandshakeStatus.HEALTHY -> { + if(!didShowConnected) { + launchVpnConnectedNotification() + didShowConnected = true + } + } + HandshakeStatus.UNHEALTHY -> { + if(!didShowFailedHandshakeNotification) { + launchVpnConnectionFailedNotification(getString(R.string.lost_connection_failure_message)) + didShowFailedHandshakeNotification = true + didShowConnected = false + } + } + } + } + } + } + + override fun stopService(extras : Bundle?) { + super.stopService(extras) + CoroutineScope(Dispatchers.IO).launch() { + vpnService.stopTunnel() + } + cancelJob() + stopSelf() + } + + private fun launchVpnConnectedNotification() { + val notification = notificationService.createNotification( + channelId = getString(R.string.vpn_channel_id), + channelName = getString(R.string.vpn_channel_name), + title = getString(R.string.tunnel_start_title), + onGoing = false, + showTimestamp = true, + description = "${getString(R.string.tunnel_start_text)} $tunnelName" + ) + super.startForeground(foregroundId, notification) + } + + private fun launchVpnStartingNotification() { + val notification = notificationService.createNotification( + channelId = getString(R.string.vpn_channel_id), + channelName = getString(R.string.vpn_channel_name), + title = getString(R.string.vpn_starting), + onGoing = false, + showTimestamp = true, + description = getString(R.string.attempt_connection) + ) + super.startForeground(foregroundId, notification) + } + + private fun launchVpnConnectionFailedNotification(message : String) { + val notification = notificationService.createNotification( + channelId = getString(R.string.vpn_channel_id), + channelName = getString(R.string.vpn_channel_name), + action = PendingIntent.getBroadcast(this,0,Intent(this, NotificationActionReceiver::class.java),PendingIntent.FLAG_IMMUTABLE), + actionText = getString(R.string.restart), + title = getString(R.string.vpn_connection_failed), + onGoing = false, + showTimestamp = true, + description = message + ) + super.startForeground(foregroundId, notification) + } + + + private fun cancelJob() { + if(this::job.isInitialized) { + job.cancel() + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/BaseNetworkService.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/BaseNetworkService.kt new file mode 100644 index 0000000000..9574d659ef --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/BaseNetworkService.kt @@ -0,0 +1,117 @@ +package net.nymtech.nymconnect.service.network + +import android.content.Context +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import android.net.NetworkRequest +import android.net.wifi.SupplicantState +import android.net.wifi.WifiInfo +import android.net.wifi.WifiManager +import android.os.Build +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.map + + +abstract class BaseNetworkService>(val context: Context, networkCapability : Int) : NetworkService { + private val connectivityManager = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + + private val wifiManager = + context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager + + override val networkStatus = callbackFlow { + val networkStatusCallback = when (Build.VERSION.SDK_INT) { + in Build.VERSION_CODES.S..Int.MAX_VALUE -> { + object : ConnectivityManager.NetworkCallback( + FLAG_INCLUDE_LOCATION_INFO + ) { + override fun onAvailable(network: Network) { + trySend(NetworkStatus.Available(network)) + } + + override fun onLost(network: Network) { + trySend(NetworkStatus.Unavailable(network)) + } + + override fun onCapabilitiesChanged( + network: Network, + networkCapabilities: NetworkCapabilities + ) { + trySend(NetworkStatus.CapabilitiesChanged(network, networkCapabilities)) + } + } + } + + else -> { + object : ConnectivityManager.NetworkCallback() { + + override fun onAvailable(network: Network) { + trySend(NetworkStatus.Available(network)) + } + + override fun onLost(network: Network) { + trySend(NetworkStatus.Unavailable(network)) + } + + override fun onCapabilitiesChanged( + network: Network, + networkCapabilities: NetworkCapabilities + ) { + trySend(NetworkStatus.CapabilitiesChanged(network, networkCapabilities)) + } + } + } + } + val request = NetworkRequest.Builder() + .addTransportType(networkCapability) + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + .build() + connectivityManager.registerNetworkCallback(request, networkStatusCallback) + + awaitClose { + connectivityManager.unregisterNetworkCallback(networkStatusCallback) + } + } + + + override fun getNetworkName(networkCapabilities: NetworkCapabilities): String? { + var ssid: String? = getWifiNameFromCapabilities(networkCapabilities) + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { + val info = wifiManager.connectionInfo + if (info.supplicantState === SupplicantState.COMPLETED) { + ssid = info.ssid + } + } + return ssid?.trim('"') + } + + + companion object { + private fun getWifiNameFromCapabilities(networkCapabilities: NetworkCapabilities): String? { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + val info: WifiInfo + if (networkCapabilities.transportInfo is WifiInfo) { + info = networkCapabilities.transportInfo as WifiInfo + return info.ssid + } + } + return null + } + } +} + +inline fun Flow.map( + crossinline onUnavailable: suspend (network : Network) -> Result, + crossinline onAvailable: suspend (network : Network) -> Result, + crossinline onCapabilitiesChanged: suspend (network : Network, networkCapabilities : NetworkCapabilities) -> Result, +): Flow = map { status -> + when (status) { + is NetworkStatus.Unavailable -> onUnavailable(status.network) + is NetworkStatus.Available -> onAvailable(status.network) + is NetworkStatus.CapabilitiesChanged -> onCapabilitiesChanged(status.network, status.networkCapabilities) + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/MobileDataService.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/MobileDataService.kt new file mode 100644 index 0000000000..a067af06cf --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/MobileDataService.kt @@ -0,0 +1,10 @@ +package net.nymtech.nymconnect.service.network + +import android.content.Context +import android.net.NetworkCapabilities +import dagger.hilt.android.qualifiers.ApplicationContext +import javax.inject.Inject + +class MobileDataService @Inject constructor(@ApplicationContext context: Context) : + BaseNetworkService(context, NetworkCapabilities.TRANSPORT_CELLULAR) { +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/NetworkService.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/NetworkService.kt new file mode 100644 index 0000000000..6c274dab03 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/NetworkService.kt @@ -0,0 +1,10 @@ +package net.nymtech.nymconnect.service.network + +import android.net.NetworkCapabilities +import kotlinx.coroutines.flow.Flow + +interface NetworkService { + fun getNetworkName(networkCapabilities: NetworkCapabilities) : String? + val networkStatus : Flow + +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/NetworkStatus.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/NetworkStatus.kt new file mode 100644 index 0000000000..5446ce52a6 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/NetworkStatus.kt @@ -0,0 +1,10 @@ +package net.nymtech.nymconnect.service.network + +import android.net.Network +import android.net.NetworkCapabilities + +sealed class NetworkStatus { + class Available(val network : Network) : NetworkStatus() + class Unavailable(val network : Network) : NetworkStatus() + class CapabilitiesChanged(val network : Network, val networkCapabilities : NetworkCapabilities) : NetworkStatus() +} diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/WifiService.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/WifiService.kt new file mode 100644 index 0000000000..a01ebba746 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/WifiService.kt @@ -0,0 +1,10 @@ +package net.nymtech.nymconnect.service.network + +import android.content.Context +import android.net.NetworkCapabilities +import dagger.hilt.android.qualifiers.ApplicationContext +import javax.inject.Inject + +class WifiService @Inject constructor(@ApplicationContext context: Context) : + BaseNetworkService(context, NetworkCapabilities.TRANSPORT_WIFI) { +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/NotificationService.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/NotificationService.kt new file mode 100644 index 0000000000..4071e64202 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/NotificationService.kt @@ -0,0 +1,21 @@ +package net.nymtech.nymconnect.service.notification + +import android.app.Notification +import android.app.NotificationManager +import android.app.PendingIntent + +interface NotificationService { + fun createNotification( + channelId: String, + channelName: String, + title: String = "", + action: PendingIntent? = null, + actionText: String? = null, + description: String, + showTimestamp : Boolean = false, + importance: Int = NotificationManager.IMPORTANCE_HIGH, + vibration: Boolean = true, + onGoing: Boolean = true, + lights: Boolean = true + ): Notification +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/WireGuardNotification.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/WireGuardNotification.kt new file mode 100644 index 0000000000..4e4cdb3e1b --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/notification/WireGuardNotification.kt @@ -0,0 +1,77 @@ +package net.nymtech.nymconnect.service.notification + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.graphics.Color +import net.nymtech.nymconnect.R +import net.nymtech.nymconnect.ui.MainActivity +import dagger.hilt.android.qualifiers.ApplicationContext +import javax.inject.Inject + +class WireGuardNotification @Inject constructor(@ApplicationContext private val context: Context) : NotificationService { + + private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager; + + override fun createNotification( + channelId: String, + channelName: String, + title: String, + action: PendingIntent?, + actionText: String?, + description: String, + showTimestamp: Boolean, + importance: Int, + vibration: Boolean, + onGoing: Boolean, + lights: Boolean + ): Notification { + val channel = NotificationChannel( + channelId, + channelName, + importance + ).let { + it.description = title + it.enableLights(lights) + it.lightColor = Color.RED + it.enableVibration(vibration) + it.vibrationPattern = longArrayOf(100, 200, 300, 400, 500, 400, 300, 200, 400) + it + } + notificationManager.createNotificationChannel(channel) + val pendingIntent: PendingIntent = + Intent(context, MainActivity::class.java).let { notificationIntent -> + PendingIntent.getActivity( + context, + 0, + notificationIntent, + PendingIntent.FLAG_IMMUTABLE + ) + } + + val builder: Notification.Builder = + Notification.Builder( + context, + channelId + ) + return builder.let { + if(action != null && actionText != null) { + //TODO find a not deprecated way to do this + it.addAction( + Notification.Action.Builder(0, actionText, action) + .build()) + it.setAutoCancel(true) + } + it.setContentTitle(title) + .setContentText(description) + .setContentIntent(pendingIntent) + .setOngoing(onGoing) + .setShowWhen(showTimestamp) + .setSmallIcon(R.mipmap.ic_launcher_foreground) + .build() + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsActivity.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsActivity.kt new file mode 100644 index 0000000000..c88825e71e --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsActivity.kt @@ -0,0 +1,28 @@ +package net.nymtech.nymconnect.service.shortcut + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import net.nymtech.nymconnect.R +import net.nymtech.nymconnect.service.foreground.Action +import net.nymtech.nymconnect.service.foreground.ServiceManager +import net.nymtech.nymconnect.service.foreground.WireGuardTunnelService +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class ShortcutsActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if(intent.getStringExtra(ShortcutsManager.CLASS_NAME_EXTRA_KEY) + .equals(WireGuardTunnelService::class.java.name)) { + intent.getStringExtra(getString(R.string.tunnel_extras_key))?.let { + ServiceManager.toggleWatcherService(this, it) + } + when(intent.action){ + Action.STOP.name -> ServiceManager.stopVpnService(this) + Action.START.name -> intent.getStringExtra(getString(R.string.tunnel_extras_key)) + ?.let { ServiceManager.startVpnService(this, it) } + } + } + finish() + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsManager.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsManager.kt new file mode 100644 index 0000000000..13df427ebd --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsManager.kt @@ -0,0 +1,73 @@ +package net.nymtech.nymconnect.service.shortcut + +import android.content.Context +import android.content.Intent +import androidx.core.content.pm.ShortcutInfoCompat +import androidx.core.content.pm.ShortcutManagerCompat +import androidx.core.graphics.drawable.IconCompat +import net.nymtech.nymconnect.R +import net.nymtech.nymconnect.service.foreground.Action +import net.nymtech.nymconnect.service.foreground.WireGuardTunnelService +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig + +object ShortcutsManager { + + private const val SHORT_LABEL_MAX_SIZE = 10; + private const val LONG_LABEL_MAX_SIZE = 25; + private const val APPEND_ON = " On"; + private const val APPEND_OFF = " Off" + const val CLASS_NAME_EXTRA_KEY = "className" + + private fun createAndPushShortcut(context : Context, intent : Intent, id : String, shortLabel : String, + longLabel : String, drawable : Int ) { + val shortcut = ShortcutInfoCompat.Builder(context, id) + .setShortLabel(shortLabel) + .setLongLabel(longLabel) + .setIcon(IconCompat.createWithResource(context, drawable)) + .setIntent(intent) + .build() + ShortcutManagerCompat.pushDynamicShortcut(context, shortcut) + } + + fun createTunnelShortcuts(context : Context, tunnelConfig : TunnelConfig) { + createAndPushShortcut(context, + createTunnelOnIntent(context, mapOf(context.getString(R.string.tunnel_extras_key) to tunnelConfig.toString())), + tunnelConfig.id.toString() + APPEND_ON, + tunnelConfig.name.take((SHORT_LABEL_MAX_SIZE - APPEND_ON.length)) + APPEND_ON, + tunnelConfig.name.take((LONG_LABEL_MAX_SIZE - APPEND_ON.length)) + APPEND_ON, + R.drawable.vpn_on + ) + createAndPushShortcut(context, + createTunnelOffIntent(context, mapOf(context.getString(R.string.tunnel_extras_key) to tunnelConfig.toString())), + tunnelConfig.id.toString() + APPEND_OFF, + tunnelConfig.name.take((SHORT_LABEL_MAX_SIZE - APPEND_OFF.length)) + APPEND_OFF, + tunnelConfig.name.take((LONG_LABEL_MAX_SIZE - APPEND_OFF.length)) + APPEND_OFF, + R.drawable.vpn_off + ) + } + + fun removeTunnelShortcuts(context : Context, tunnelConfig : TunnelConfig) { + ShortcutManagerCompat.removeDynamicShortcuts(context, listOf(tunnelConfig.id.toString() + APPEND_ON, + tunnelConfig.id.toString() + APPEND_OFF )) + } + + private fun createTunnelOnIntent(context: Context, extras : Map) : Intent { + return Intent(context, ShortcutsActivity::class.java).also { + it.action = Action.START.name + it.putExtra(CLASS_NAME_EXTRA_KEY, WireGuardTunnelService::class.java.name) + extras.forEach {(k, v) -> + it.putExtra(k, v) + } + } + } + + private fun createTunnelOffIntent(context : Context, extras : Map) : Intent { + return Intent(context, ShortcutsActivity::class.java).also { + it.action = Action.STOP.name + it.putExtra(CLASS_NAME_EXTRA_KEY, WireGuardTunnelService::class.java.name) + extras.forEach {(k, v) -> + it.putExtra(k, v) + } + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt new file mode 100644 index 0000000000..38c774c963 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt @@ -0,0 +1,142 @@ +package net.nymtech.nymconnect.service.tile + +import android.os.Build +import android.service.quicksettings.Tile +import android.service.quicksettings.TileService +import com.wireguard.android.backend.Tunnel +import net.nymtech.nymconnect.R +import net.nymtech.nymconnect.repository.Repository +import net.nymtech.nymconnect.service.foreground.ServiceManager +import net.nymtech.nymconnect.service.tunnel.VpnService +import net.nymtech.nymconnect.service.tunnel.model.Settings +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel +import kotlinx.coroutines.launch +import timber.log.Timber +import javax.inject.Inject + +@AndroidEntryPoint +class TunnelControlTile : TileService() { + + @Inject + lateinit var settingsRepo : Repository + + @Inject + lateinit var configRepo : Repository + + @Inject + lateinit var vpnService : VpnService + + private val scope = CoroutineScope(Dispatchers.Main); + + private lateinit var job : Job + + override fun onStartListening() { + job = scope.launch { + updateTileState() + } + super.onStartListening() + } + + override fun onTileAdded() { + super.onTileAdded() + qsTile.contentDescription = this.resources.getString(R.string.toggle_vpn) + scope.launch { + updateTileState(); + } + } + + override fun onTileRemoved() { + super.onTileRemoved() + cancelJob() + } + + override fun onClick() { + super.onClick() + unlockAndRun { + scope.launch { + try { + val tunnel = determineTileTunnel(); + if(tunnel != null) { + attemptWatcherServiceToggle(tunnel.toString()) + if(vpnService.getState() == Tunnel.State.UP) { + ServiceManager.stopVpnService(this@TunnelControlTile) + } else { + ServiceManager.startVpnService(this@TunnelControlTile, tunnel.toString()) + } + } + } catch (e : Exception) { + Timber.e(e.message) + } finally { + cancel() + } + } + } + } + + private suspend fun determineTileTunnel() : TunnelConfig? { + var tunnelConfig : TunnelConfig? = null; + val settings = settingsRepo.getAll() + if (!settings.isNullOrEmpty()) { + val setting = settings.first() + tunnelConfig = if (setting.defaultTunnel != null) { + TunnelConfig.from(setting.defaultTunnel!!); + } else { + val config = configRepo.getAll()?.first(); + config; + } + } + return tunnelConfig; + } + + + private fun attemptWatcherServiceToggle(tunnelConfig : String) { + scope.launch { + val settings = settingsRepo.getAll() + if (!settings.isNullOrEmpty()) { + val setting = settings.first() + if(setting.isAutoTunnelEnabled) { + ServiceManager.toggleWatcherService(this@TunnelControlTile, tunnelConfig) + } + } + } + } + + private suspend fun updateTileState() { + vpnService.state.collect { + when(it) { + Tunnel.State.UP -> { + qsTile.state = Tile.STATE_ACTIVE + } + Tunnel.State.DOWN -> { + qsTile.state = Tile.STATE_INACTIVE; + } + else -> { + qsTile.state = Tile.STATE_UNAVAILABLE + } + } + val config = determineTileTunnel(); + setTileDescription(config?.name ?: this.resources.getString(R.string.no_tunnel_available)) + qsTile.updateTile() + } + } + + private fun setTileDescription(description : String) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + qsTile.subtitle = description + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + qsTile.stateDescription = description; + } + } + + private fun cancelJob() { + if(this::job.isInitialized) { + job.cancel(); + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/HandshakeStatus.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/HandshakeStatus.kt new file mode 100644 index 0000000000..1d2fa54ea7 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/HandshakeStatus.kt @@ -0,0 +1,14 @@ +package net.nymtech.nymconnect.service.tunnel + +enum class HandshakeStatus { + HEALTHY, + UNHEALTHY, + NEVER_CONNECTED, + NOT_STARTED; + + companion object { + private const val WG_TYPICAL_HANDSHAKE_INTERVAL_WHEN_HEALTHY_SEC = 120 + const val UNHEALTHY_TIME_LIMIT_SEC = WG_TYPICAL_HANDSHAKE_INTERVAL_WHEN_HEALTHY_SEC + 60 + const val NEVER_CONNECTED_TO_UNHEALTHY_TIME_LIMIT_SEC = 30 + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/VpnService.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/VpnService.kt new file mode 100644 index 0000000000..15c8c1b676 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/VpnService.kt @@ -0,0 +1,18 @@ +package net.nymtech.nymconnect.service.tunnel + +import com.wireguard.android.backend.Statistics +import com.wireguard.android.backend.Tunnel +import com.wireguard.crypto.Key +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig +import kotlinx.coroutines.flow.SharedFlow + +interface VpnService : Tunnel { + suspend fun startTunnel(tunnelConfig : TunnelConfig) : Tunnel.State + suspend fun stopTunnel() + val state : SharedFlow + val tunnelName : SharedFlow + val statistics : SharedFlow + val lastHandshake : SharedFlow> + val handshakeStatus : SharedFlow + fun getState() : Tunnel.State +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt new file mode 100644 index 0000000000..ae9a3c233d --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt @@ -0,0 +1,131 @@ +package net.nymtech.nymconnect.service.tunnel + +import com.wireguard.android.backend.Backend +import com.wireguard.android.backend.BackendException +import com.wireguard.android.backend.Statistics +import com.wireguard.android.backend.Tunnel +import com.wireguard.crypto.Key +import net.nymtech.nymconnect.Constants +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig +import net.nymtech.nymconnect.util.NumberUtils +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import timber.log.Timber +import javax.inject.Inject + + +class WireGuardTunnel @Inject constructor(private val backend : Backend, +) : VpnService { + + private val _tunnelName = MutableStateFlow("") + override val tunnelName get() = _tunnelName.asStateFlow() + + private val _state = MutableSharedFlow( + onBufferOverflow = BufferOverflow.DROP_OLDEST, + replay = 1) + + private val _handshakeStatus = MutableSharedFlow(replay = 1, + onBufferOverflow = BufferOverflow.DROP_OLDEST) + override val state get() = _state.asSharedFlow() + + private val _statistics = MutableSharedFlow(replay = 1) + override val statistics get() = _statistics.asSharedFlow() + + private val _lastHandshake = MutableSharedFlow>(replay = 1) + override val lastHandshake get() = _lastHandshake.asSharedFlow() + + override val handshakeStatus: SharedFlow + get() = _handshakeStatus.asSharedFlow() + + private lateinit var statsJob : Job + + + override suspend fun startTunnel(tunnelConfig: TunnelConfig) : Tunnel.State{ + return try { + if(getState() == Tunnel.State.UP && _tunnelName.value != tunnelConfig.name) { + stopTunnel() + } + _tunnelName.emit(tunnelConfig.name) + val config = TunnelConfig.configFromQuick(tunnelConfig.wgQuick) + val state = backend.setState( + this, Tunnel.State.UP, config) + _state.emit(state) + state; + } catch (e : Exception) { + Timber.e("Failed to start tunnel with error: ${e.message}") + Tunnel.State.DOWN + } + } + + override fun getName(): String { + return _tunnelName.value + } + + override suspend fun stopTunnel() { + try { + if(getState() == Tunnel.State.UP) { + val state = backend.setState(this, Tunnel.State.DOWN, null) + _state.emit(state) + } + } catch (e : BackendException) { + Timber.e("Failed to stop tunnel with error: ${e.message}") + } + } + + override fun getState(): Tunnel.State { + return backend.getState(this) + } + + override fun onStateChange(state : Tunnel.State) { + val tunnel = this; + _state.tryEmit(state) + if(state == Tunnel.State.UP) { + statsJob = CoroutineScope(Dispatchers.IO).launch { + val handshakeMap = HashMap() + var neverHadHandshakeCounter = 0 + while (true) { + val statistics = backend.getStatistics(tunnel) + _statistics.emit(statistics) + statistics.peers().forEach { + val handshakeEpoch = statistics.peer(it)?.latestHandshakeEpochMillis ?: 0L + handshakeMap[it] = handshakeEpoch + if(handshakeEpoch == 0L) { + if(neverHadHandshakeCounter >= HandshakeStatus.NEVER_CONNECTED_TO_UNHEALTHY_TIME_LIMIT_SEC) { + _handshakeStatus.emit(HandshakeStatus.NEVER_CONNECTED) + } else { + _handshakeStatus.emit(HandshakeStatus.NOT_STARTED) + } + if(neverHadHandshakeCounter <= HandshakeStatus.NEVER_CONNECTED_TO_UNHEALTHY_TIME_LIMIT_SEC) { + neverHadHandshakeCounter += 10 + } + return@forEach + } + if(NumberUtils.getSecondsBetweenTimestampAndNow(handshakeEpoch) >= HandshakeStatus.UNHEALTHY_TIME_LIMIT_SEC) { + _handshakeStatus.emit(HandshakeStatus.UNHEALTHY) + } else { + _handshakeStatus.emit(HandshakeStatus.HEALTHY) + } + } + _lastHandshake.emit(handshakeMap) + delay(Constants.VPN_STATISTIC_CHECK_INTERVAL) + } + } + } + if(state == Tunnel.State.DOWN) { + if(this::statsJob.isInitialized) { + statsJob.cancel() + } + _handshakeStatus.tryEmit(HandshakeStatus.NOT_STARTED) + _lastHandshake.tryEmit(emptyMap()) + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/model/Settings.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/model/Settings.kt new file mode 100644 index 0000000000..2aff4e9f11 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/model/Settings.kt @@ -0,0 +1,15 @@ +package net.nymtech.nymconnect.service.tunnel.model + +import io.objectbox.annotation.Entity +import io.objectbox.annotation.Id + +@Entity +data class Settings( + @Id + var id : Long = 0, + var isAutoTunnelEnabled : Boolean = false, + var isTunnelOnMobileDataEnabled : Boolean = false, + var trustedNetworkSSIDs : MutableList = mutableListOf(), + var defaultTunnel : String? = null, + var isAlwaysOnVpnEnabled : Boolean = false, +) diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/model/TunnelConfig.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/model/TunnelConfig.kt new file mode 100644 index 0000000000..91f7440d0d --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/model/TunnelConfig.kt @@ -0,0 +1,89 @@ +package net.nymtech.nymconnect.service.tunnel.model + +import com.wireguard.config.Config +import io.objectbox.annotation.ConflictStrategy +import io.objectbox.annotation.Entity +import io.objectbox.annotation.Id +import io.objectbox.annotation.Unique +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import java.io.InputStream + + +@Entity +@Serializable +data class TunnelConfig( + @Id + var id : Long = 0, + @Unique(onConflict = ConflictStrategy.REPLACE) + var name : String, + var wgQuick : String +) { + + + override fun toString(): String { + return Json.encodeToString(serializer(), this) + } + + companion object { + private const val INCLUDED_APPLICATIONS = "IncludedApplications = " + private const val EXCLUDED_APPLICATIONS = "ExcludedApplications = " + private const val INTERFACE = "[Interface]" + private const val NEWLINE_CHAR = "\n" + private const val APP_CONFIG_SEPARATOR = ", " + + private fun addApplicationsToConfig(appConfig : String, wgQuick : String) : String { + val configList = wgQuick.split(NEWLINE_CHAR).toMutableList() + val interfaceIndex = configList.indexOf(INTERFACE) + configList.add(interfaceIndex + 1, appConfig) + return configList.joinToString(NEWLINE_CHAR) + } + + fun clearAllApplicationsFromConfig(wgQuick : String) : String { + val configList = wgQuick.split(NEWLINE_CHAR).toMutableList() + val itr = configList.iterator() + while (itr.hasNext()) { + val next = itr.next() + if(next.contains(INCLUDED_APPLICATIONS) || next.contains(EXCLUDED_APPLICATIONS)) { + itr.remove() + } + } + return configList.joinToString(NEWLINE_CHAR) + } + + + fun setExcludedApplicationsOnQuick(packages : List, wgQuick: String) : String { + if(packages.isEmpty()) { + return wgQuick + } + val clearedWgQuick = clearAllApplicationsFromConfig(wgQuick) + val excludeConfig = buildExcludedApplicationsString(packages) + return addApplicationsToConfig(excludeConfig, clearedWgQuick) + } + + fun setIncludedApplicationsOnQuick(packages : List, wgQuick: String) : String { + if(packages.isEmpty()) { + return wgQuick + } + val clearedWgQuick = clearAllApplicationsFromConfig(wgQuick) + val includeConfig = buildIncludedApplicationsString(packages) + return addApplicationsToConfig(includeConfig, clearedWgQuick) + } + + private fun buildExcludedApplicationsString(packages : List) : String { + return EXCLUDED_APPLICATIONS + packages.joinToString(APP_CONFIG_SEPARATOR) + } + + private fun buildIncludedApplicationsString(packages : List) : String { + return INCLUDED_APPLICATIONS + packages.joinToString(APP_CONFIG_SEPARATOR) + } + fun from(string : String) : TunnelConfig { + return Json.decodeFromString(string) + } + fun configFromQuick(wgQuick: String): Config { + val inputStream: InputStream = wgQuick.byteInputStream() + val reader = inputStream.bufferedReader(Charsets.UTF_8) + return Config.parse(reader) + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt new file mode 100644 index 0000000000..edb82cc213 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt @@ -0,0 +1,201 @@ +package net.nymtech.nymconnect.ui + +import android.Manifest +import android.content.Intent +import android.net.Uri +import android.os.Build +import android.os.Bundle +import android.provider.Settings +import android.view.KeyEvent +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.compose.setContent +import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AppCompatActivity +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.slideInHorizontally +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.input.key.onKeyEvent +import com.google.accompanist.navigation.animation.AnimatedNavHost +import com.google.accompanist.navigation.animation.composable +import com.google.accompanist.navigation.animation.rememberAnimatedNavController +import com.google.accompanist.permissions.ExperimentalPermissionsApi +import com.google.accompanist.permissions.isGranted +import com.google.accompanist.permissions.rememberPermissionState +import com.wireguard.android.backend.GoBackend +import net.nymtech.nymconnect.R +import net.nymtech.nymconnect.ui.common.PermissionRequestFailedScreen +import net.nymtech.nymconnect.ui.common.navigation.BottomNavBar +import net.nymtech.nymconnect.ui.screens.config.ConfigScreen +import net.nymtech.nymconnect.ui.screens.detail.DetailScreen +import net.nymtech.nymconnect.ui.screens.main.MainScreen +import net.nymtech.nymconnect.ui.screens.settings.SettingsScreen +import net.nymtech.nymconnect.ui.screens.support.SupportScreen +import net.nymtech.nymconnect.ui.theme.TransparentSystemBars +import net.nymtech.nymconnect.ui.theme.WireguardAutoTunnelTheme +import dagger.hilt.android.AndroidEntryPoint +import timber.log.Timber +import java.lang.IllegalStateException + +@AndroidEntryPoint +class MainActivity : AppCompatActivity() { + + @OptIn(ExperimentalAnimationApi::class, + ExperimentalPermissionsApi::class + ) + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + val navController = rememberAnimatedNavController() + val focusRequester = remember { FocusRequester() } + + WireguardAutoTunnelTheme { + TransparentSystemBars() + + val snackbarHostState = remember { SnackbarHostState() } + + val notificationPermissionState = + rememberPermissionState(Manifest.permission.POST_NOTIFICATIONS) + + fun requestNotificationPermission() { + if (!notificationPermissionState.status.isGranted && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + notificationPermissionState.launchPermissionRequest() + } + } + + var vpnIntent by remember { mutableStateOf(GoBackend.VpnService.prepare(this)) } + val vpnActivityResultState = rememberLauncherForActivityResult( + ActivityResultContracts.StartActivityForResult(), + onResult = { + val accepted = (it.resultCode == RESULT_OK) + if (accepted) { + vpnIntent = null + } + }) + LaunchedEffect(vpnIntent) { + if (vpnIntent != null) { + vpnActivityResultState.launch(vpnIntent) + } else requestNotificationPermission() + } + + Scaffold(snackbarHost = { SnackbarHost(snackbarHostState)}, + modifier = Modifier.onKeyEvent { + if (it.nativeKeyEvent.action == KeyEvent.ACTION_UP) { + when (it.nativeKeyEvent.keyCode) { + KeyEvent.KEYCODE_DPAD_UP -> { + try { + focusRequester.requestFocus() + } catch(e : IllegalStateException) { + Timber.e("No D-Pad focus request modifier added to element on screen") + } + false + } else -> { + false; + } + } + } else { + false + } + }, + bottomBar = if (vpnIntent == null && notificationPermissionState.status.isGranted) { + { BottomNavBar(navController, Routes.navItems) } + } else { + {} + }, + ) + { padding -> + if (vpnIntent != null) { + PermissionRequestFailedScreen( + padding = padding, + onRequestAgain = { vpnActivityResultState.launch(vpnIntent) }, + message = getString(R.string.vpn_permission_required), + getString(R.string.retry) + ) + return@Scaffold + } + if (!notificationPermissionState.status.isGranted) { + PermissionRequestFailedScreen( + padding = padding, + onRequestAgain = { + val intentSettings = + Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) + intentSettings.data = + Uri.fromParts("package", this.packageName, null) + startActivity(intentSettings); + }, + message = getString(R.string.notification_permission_required), + getString(R.string.open_settings) + ) + return@Scaffold + } + AnimatedNavHost(navController, startDestination = Routes.Main.name) { + composable(Routes.Main.name, enterTransition = { + when (initialState.destination.route) { + Routes.Settings.name, Routes.Support.name -> + slideInHorizontally( + initialOffsetX = { -1000 }, + animationSpec = tween(500) + ) + + else -> { + fadeIn(animationSpec = tween(1000)) + } + } + }) { + MainScreen(padding = padding, snackbarHostState = snackbarHostState, navController = navController) + } + composable(Routes.Settings.name, enterTransition = { + when (initialState.destination.route) { + Routes.Main.name -> + slideInHorizontally( + initialOffsetX = { 1000 }, + animationSpec = tween(500) + ) + + Routes.Support.name -> { + slideInHorizontally( + initialOffsetX = { -1000 }, + animationSpec = tween(500) + ) + } + + else -> { + fadeIn(animationSpec = tween(1000)) + } + } + }) { SettingsScreen(padding = padding, snackbarHostState = snackbarHostState, navController = navController, focusRequester = focusRequester) } + composable(Routes.Support.name, enterTransition = { + when (initialState.destination.route) { + Routes.Settings.name, Routes.Main.name -> + slideInHorizontally( + initialOffsetX = { 1000 }, + animationSpec = tween(500) + ) + + else -> { + fadeIn(animationSpec = tween(1000)) + } + } + }) { SupportScreen(padding = padding, focusRequester) } + composable("${Routes.Config.name}/{id}", enterTransition = { + fadeIn(animationSpec = tween(1000)) + }) { ConfigScreen(padding = padding, navController = navController, id = it.arguments?.getString("id"), focusRequester = focusRequester)} + composable("${Routes.Detail.name}/{id}", enterTransition = { + fadeIn(animationSpec = tween(1000)) + }) { DetailScreen(padding = padding, id = it.arguments?.getString("id")) } + } + } + } + } + } +} diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/Routes.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/Routes.kt new file mode 100644 index 0000000000..589fa5fbbf --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/Routes.kt @@ -0,0 +1,36 @@ +package net.nymtech.nymconnect.ui + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.Home +import androidx.compose.material.icons.rounded.QuestionMark +import androidx.compose.material.icons.rounded.Settings +import net.nymtech.nymconnect.ui.common.navigation.BottomNavItem + +enum class Routes { + Main, + Settings, + Support, + Config, + Detail; + + + companion object { + val navItems = listOf( + BottomNavItem( + name = "Tunnels", + route = Main.name, + icon = Icons.Rounded.Home, + ), + BottomNavItem( + name = "Settings", + route = Settings.name, + icon = Icons.Rounded.Settings, + ), + BottomNavItem( + name = "Support", + route = Support.name, + icon = Icons.Rounded.QuestionMark, + ) + ) + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/ViewState.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/ViewState.kt new file mode 100644 index 0000000000..66aa0b8790 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/ViewState.kt @@ -0,0 +1,9 @@ +package net.nymtech.nymconnect.ui + +data class ViewState( + val showSnackbarMessage : Boolean = false, + val snackbarMessage : String = "", + val snackbarActionText : String = "", + val onSnackbarActionClick : () -> Unit = {}, + val isLoading : Boolean = false +) diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/ClickableIconButton.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/ClickableIconButton.kt new file mode 100644 index 0000000000..2ddd1f27b2 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/ClickableIconButton.kt @@ -0,0 +1,31 @@ +package net.nymtech.nymconnect.ui.common + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector + +@Composable +fun ClickableIconButton(onIconClick : () -> Unit, text : String, icon : ImageVector, enabled : Boolean) { + Button(onClick = {}, + enabled = enabled + ) { + Text(text) + Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing)) + Icon( + imageVector = icon, + contentDescription = "Delete", + modifier = Modifier.size(ButtonDefaults.IconSize).clickable { + if(enabled) { + onIconClick() + } + } + ) + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/PermissionRequestFailedScreen.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/PermissionRequestFailedScreen.kt new file mode 100644 index 0000000000..a0f81b5745 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/PermissionRequestFailedScreen.kt @@ -0,0 +1,35 @@ +package net.nymtech.nymconnect.ui.common + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import kotlinx.coroutines.launch + +@Composable +fun PermissionRequestFailedScreen(padding : PaddingValues, onRequestAgain : () -> Unit, message : String, buttonText : String ) { + val scope = rememberCoroutineScope() + Column(horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxSize() + .padding(padding)) { + Text(message, textAlign = TextAlign.Center, modifier = Modifier.padding(15.dp)) + Button(onClick = { + scope.launch { + onRequestAgain() + } + }) { + Text(buttonText) + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/RowListItem.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/RowListItem.kt new file mode 100644 index 0000000000..33fb6d0bf6 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/RowListItem.kt @@ -0,0 +1,55 @@ +package net.nymtech.nymconnect.ui.common + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp + +@OptIn(ExperimentalFoundationApi::class) +@Composable +fun RowListItem(leadingIcon : ImageVector? = null, leadingIconColor : Color = Color.Gray, text : String, onHold : () -> Unit, onClick: () -> Unit, rowButton : @Composable() () -> Unit ) { + Box( + modifier = Modifier + .combinedClickable( + onClick = { + onClick() + }, + onLongClick = { + onHold() + } + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(14.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row(verticalAlignment = Alignment.CenterVertically,) { + if(leadingIcon != null) { + Icon( + leadingIcon, "status", + tint = leadingIconColor, + modifier = Modifier.padding(end = 10.dp).size(15.dp) + ) + } + Text(text) + } + + rowButton() + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/SearchBar.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/SearchBar.kt new file mode 100644 index 0000000000..cec26f5b09 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/SearchBar.kt @@ -0,0 +1,80 @@ +package net.nymtech.nymconnect.ui.common + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.Clear +import androidx.compose.material.icons.rounded.Search +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardType +import net.nymtech.nymconnect.R + +@Composable +fun SearchBar( + onQuery : (queryString : String) -> Unit +) { + // Immediately update and keep track of query from text field changes. + var query: String by rememberSaveable { mutableStateOf("") } + var showClearIcon by rememberSaveable { mutableStateOf(false) } + + if (query.isEmpty()) { + showClearIcon = false + } else if (query.isNotEmpty()) { + showClearIcon = true + } + + TextField( + value = query, + onValueChange = { onQueryChanged -> + // If user makes changes to text, immediately updated it. + query = onQueryChanged + onQuery(onQueryChanged) + }, + leadingIcon = { + Icon( + imageVector = Icons.Rounded.Search, + tint = MaterialTheme.colorScheme.onBackground, + contentDescription = stringResource(id = R.string.search_icon) + ) + }, + trailingIcon = { + if (showClearIcon) { + IconButton(onClick = { query = "" }) { + Icon( + imageVector = Icons.Rounded.Clear, + tint = MaterialTheme.colorScheme.onBackground, + contentDescription = stringResource(id = R.string.clear_icon) + ) + } + } + }, + maxLines = 1, + colors = TextFieldDefaults.colors( + focusedContainerColor = Color.Transparent, + unfocusedContainerColor = Color.Transparent, + disabledContainerColor = Color.Transparent, + ), + placeholder = { Text(text = stringResource(R.string.hint_search_packages)) }, + textStyle = MaterialTheme.typography.bodySmall, + singleLine = true, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text), + modifier = Modifier + .fillMaxWidth() + .background(color = MaterialTheme.colorScheme.background, shape = RectangleShape) + ) +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/navigation/BottomNavBar.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/navigation/BottomNavBar.kt new file mode 100644 index 0000000000..957228eece --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/navigation/BottomNavBar.kt @@ -0,0 +1,42 @@ +package net.nymtech.nymconnect.ui.common.navigation + +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.font.FontWeight +import androidx.navigation.NavController +import androidx.navigation.compose.currentBackStackEntryAsState + +@Composable +fun BottomNavBar(navController : NavController, bottomNavItems : List) { + + val backStackEntry = navController.currentBackStackEntryAsState() + + NavigationBar( + containerColor = MaterialTheme.colorScheme.background, + ) { + bottomNavItems.forEach { item -> + val selected = item.route == backStackEntry.value?.destination?.route + + NavigationBarItem( + selected = selected, + onClick = { navController.navigate(item.route) }, + label = { + Text( + text = item.name, + fontWeight = FontWeight.SemiBold, + ) + }, + icon = { + Icon( + imageVector = item.icon, + contentDescription = "${item.name} Icon", + ) + } + ) + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/navigation/BottomNavItem.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/navigation/BottomNavItem.kt new file mode 100644 index 0000000000..a4a585ce5e --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/common/navigation/BottomNavItem.kt @@ -0,0 +1,9 @@ +package net.nymtech.nymconnect.ui.common.navigation + +import androidx.compose.ui.graphics.vector.ImageVector + +data class BottomNavItem( + val name: String, + val route: String, + val icon: ImageVector, +) diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigScreen.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigScreen.kt new file mode 100644 index 0000000000..1ecfaf6570 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigScreen.kt @@ -0,0 +1,241 @@ +package net.nymtech.nymconnect.ui.screens.config + +import android.widget.Toast +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.Android +import androidx.compose.material3.Button +import androidx.compose.material3.Checkbox +import androidx.compose.material3.Icon +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardCapitalization +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.navigation.NavController +import com.google.accompanist.drawablepainter.DrawablePainter +import net.nymtech.nymconnect.R +import net.nymtech.nymconnect.ui.Routes +import net.nymtech.nymconnect.ui.common.SearchBar +import kotlinx.coroutines.launch + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +fun ConfigScreen( + viewModel: ConfigViewModel = hiltViewModel(), + padding: PaddingValues, + focusRequester: FocusRequester, + navController: NavController, + id : String? +) { + + val context = LocalContext.current + val focusManager = LocalFocusManager.current + + val keyboardController = LocalSoftwareKeyboardController.current + val scope = rememberCoroutineScope() + val tunnel by viewModel.tunnel.collectAsStateWithLifecycle(null) + val tunnelName = viewModel.tunnelName.collectAsStateWithLifecycle() + val packages by viewModel.packages.collectAsStateWithLifecycle() + val checkedPackages by viewModel.checkedPackages.collectAsStateWithLifecycle() + val include by viewModel.include.collectAsStateWithLifecycle() + val allApplications by viewModel.allApplications.collectAsStateWithLifecycle() + + LaunchedEffect(Unit) { + viewModel.getTunnelById(id) + viewModel.emitQueriedPackages("") + viewModel.emitCurrentPackageConfigurations(id) + } + + if(tunnel != null) { + LazyColumn( + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.Top, + modifier = Modifier + .fillMaxSize() + .padding(padding) + ) { + item { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp, vertical = 7.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + OutlinedTextField( + modifier = Modifier.focusRequester(focusRequester), + value = tunnelName.value, + onValueChange = { + viewModel.onTunnelNameChange(it) + }, + label = { Text(stringResource(id = R.string.tunnel_name)) }, + maxLines = 1, + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.None, + imeAction = ImeAction.Done + ), + keyboardActions = KeyboardActions( + onDone = { + focusManager.clearFocus() + keyboardController?.hide() + viewModel.onTunnelNameChange(tunnelName.value) + } + ), + ) + } + } + item { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp, vertical = 7.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text(stringResource(id = R.string.tunnel_all)) + Switch( + checked = allApplications, + onCheckedChange = { + viewModel.onAllApplicationsChange(!allApplications) + } + ) + } + } + if (!allApplications) { + item { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp, vertical = 7.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text(stringResource(id = R.string.include)) + Checkbox( + checked = include, + onCheckedChange = { + viewModel.onIncludeChange(!include) + } + ) + } + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text(stringResource(id = R.string.exclude)) + Checkbox( + checked = !include, + onCheckedChange = { + viewModel.onIncludeChange(!include) + } + ) + } + } + } + item { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp, vertical = 7.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween) { + SearchBar(viewModel::emitQueriedPackages); + } + } + items(packages) { pack -> + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row( + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(5.dp) + ) { + val drawable = + pack.applicationInfo?.loadIcon(context.packageManager) + if (drawable != null) { + Image( + painter = DrawablePainter(drawable), + stringResource(id = R.string.icon), + modifier = Modifier.size(50.dp, 50.dp) + ) + } else { + Icon( + Icons.Rounded.Android, + stringResource(id = R.string.edit), + modifier = Modifier.size(50.dp, 50.dp) + ) + } + Text( + pack.applicationInfo.loadLabel(context.packageManager) + .toString(), modifier = Modifier.padding(5.dp) + ) + } + Checkbox( + checked = (checkedPackages.contains(pack.packageName)), + onCheckedChange = { + if (it) viewModel.onAddCheckedPackage(pack.packageName) else viewModel.onRemoveCheckedPackage( + pack.packageName + ) + } + ) + } + } + } + item { + Row( + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Button(onClick = { + scope.launch { + viewModel.onSaveAllChanges() + Toast.makeText( + context, + context.resources.getString(R.string.config_changes_saved), + Toast.LENGTH_LONG + ).show() + navController.navigate(Routes.Main.name) + } + }, Modifier.padding(25.dp)) { + Text(stringResource(id = R.string.save_changes)) + } + } + } + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigViewModel.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigViewModel.kt new file mode 100644 index 0000000000..325e5a49bd --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigViewModel.kt @@ -0,0 +1,152 @@ +package net.nymtech.nymconnect.ui.screens.config + +import android.Manifest +import android.app.Application +import android.content.pm.PackageInfo +import android.content.pm.PackageManager +import android.os.Build +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.toMutableStateList +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import net.nymtech.nymconnect.repository.Repository +import net.nymtech.nymconnect.service.tunnel.model.Settings +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import timber.log.Timber +import javax.inject.Inject + +@HiltViewModel +class ConfigViewModel @Inject constructor(private val application : Application, + private val tunnelRepo : Repository, + private val settingsRepo : Repository) : ViewModel() { + + private val _tunnel = MutableStateFlow(null) + private val _tunnelName = MutableStateFlow("") + val tunnelName get() = _tunnelName.asStateFlow() + val tunnel get() = _tunnel.asStateFlow() + private val _packages = MutableStateFlow(emptyList()) + val packages get() = _packages.asStateFlow() + private val packageManager = application.packageManager + + private val _checkedPackages = MutableStateFlow(mutableStateListOf()) + val checkedPackages get() = _checkedPackages.asStateFlow() + private val _include = MutableStateFlow(true) + val include get() = _include.asStateFlow() + + private val _allApplications = MutableStateFlow(true) + val allApplications get() = _allApplications.asStateFlow() + + suspend fun getTunnelById(id : String?) : TunnelConfig? { + return try { + if(id != null) { + val config = tunnelRepo.getById(id.toLong()) + if (config != null) { + _tunnel.emit(config) + _tunnelName.emit(config.name) + + } + return config + } + return null + } catch (e : Exception) { + Timber.e(e.message) + null + } + } + + fun onTunnelNameChange(name : String) { + _tunnelName.value = name + } + + fun onIncludeChange(include : Boolean) { + _include.value = include + } + fun onAddCheckedPackage(packageName : String) { + _checkedPackages.value.add(packageName) + } + + fun onAllApplicationsChange(allApplications : Boolean) { + _allApplications.value = allApplications + } + + fun onRemoveCheckedPackage(packageName : String) { + _checkedPackages.value.remove(packageName) + } + + suspend fun emitCurrentPackageConfigurations(id : String?) { + val tunnelConfig = getTunnelById(id) + if(tunnelConfig != null) { + val config = TunnelConfig.configFromQuick(tunnelConfig.wgQuick) + val excludedApps = config.`interface`.excludedApplications + val includedApps = config.`interface`.includedApplications + if(excludedApps.isNullOrEmpty() && includedApps.isNullOrEmpty()) { + _allApplications.emit(true) + return + } + if(excludedApps.isEmpty()) { + _include.emit(true) + _checkedPackages.emit(includedApps.toMutableStateList()) + } else { + _include.emit(false) + _checkedPackages.emit(excludedApps.toMutableStateList()) + } + _allApplications.emit(false) + } + } + + fun emitQueriedPackages(query : String) { + viewModelScope.launch { + _packages.emit(getAllInternetCapablePackages().filter { + it.packageName.contains(query) + }) + } + } + + private fun getAllInternetCapablePackages() : List { + return getPackagesHoldingPermissions(arrayOf(Manifest.permission.INTERNET)) + } + + private fun getPackagesHoldingPermissions(permissions: Array): List { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + packageManager.getPackagesHoldingPermissions(permissions, PackageManager.PackageInfoFlags.of(0L)) + } else { + @Suppress("DEPRECATION") + packageManager.getPackagesHoldingPermissions(permissions, 0) + } + } + + suspend fun onSaveAllChanges() { + var wgQuick = _tunnel.value?.wgQuick + if(wgQuick != null) { + wgQuick = if(_include.value) { + TunnelConfig.setIncludedApplicationsOnQuick(_checkedPackages.value, wgQuick) + } else { + TunnelConfig.setExcludedApplicationsOnQuick(_checkedPackages.value, wgQuick) + } + if(_allApplications.value) { + wgQuick = TunnelConfig.clearAllApplicationsFromConfig(wgQuick) + } + _tunnel.value?.copy( + name = _tunnelName.value, + wgQuick = wgQuick + )?.let { + tunnelRepo.save(it) + val settings = settingsRepo.getAll() + if(settings != null) { + val setting = settings[0] + if(setting.defaultTunnel != null) { + if(it.id == TunnelConfig.from(setting.defaultTunnel!!).id) { + settingsRepo.save(setting.copy( + defaultTunnel = it.toString() + )) + } + } + } + } + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/detail/DetailScreen.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/detail/DetailScreen.kt new file mode 100644 index 0000000000..bdf77a5e56 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/detail/DetailScreen.kt @@ -0,0 +1,139 @@ +package net.nymtech.nymconnect.ui.screens.detail + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.ClipboardManager +import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import net.nymtech.nymconnect.R +import net.nymtech.nymconnect.util.NumberUtils +import java.time.Duration +import java.time.Instant + +@Composable +fun DetailScreen( + viewModel: DetailViewModel = hiltViewModel(), + padding: PaddingValues, + id : String? +) { + + val clipboardManager: ClipboardManager = LocalClipboardManager.current + val tunnelStats by viewModel.tunnelStats.collectAsStateWithLifecycle(null) + val tunnel by viewModel.tunnel.collectAsStateWithLifecycle(null) + val tunnelName by viewModel.tunnelName.collectAsStateWithLifecycle() + val lastHandshake by viewModel.lastHandshake.collectAsStateWithLifecycle(emptyMap()) + + + LaunchedEffect(Unit) { + viewModel.getTunnelById(id) + } + + if(tunnel != null) { + val interfaceKey = tunnel?.`interface`?.keyPair?.publicKey?.toBase64().toString() + val addresses = tunnel?.`interface`?.addresses!!.joinToString() + val dnsServers = tunnel?.`interface`?.dnsServers!!.joinToString() + val optionalMtu = tunnel?.`interface`?.mtu + val mtu = if(optionalMtu?.isPresent == true) optionalMtu.get().toString() else "None" + Column( + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.Top, + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(padding) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp, vertical = 7.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Column { + Text(stringResource(R.string.config_interface), fontWeight = FontWeight.Bold, fontSize = 20.sp) + Text(stringResource(R.string.name), fontStyle = FontStyle.Italic) + Text(text = tunnelName, modifier = Modifier.clickable { + clipboardManager.setText(AnnotatedString(tunnelName)) + }) + Text(stringResource(R.string.public_key), fontStyle = FontStyle.Italic) + Text(text = interfaceKey, modifier = Modifier.clickable { + clipboardManager.setText(AnnotatedString(interfaceKey)) + }) + Text(stringResource(R.string.addresses), fontStyle = FontStyle.Italic) + Text(text = addresses, modifier = Modifier.clickable { + clipboardManager.setText(AnnotatedString(addresses)) + }) + Text(stringResource(R.string.dns_servers), fontStyle = FontStyle.Italic) + Text(text = dnsServers, modifier = Modifier.clickable { + clipboardManager.setText(AnnotatedString(dnsServers)) + }) + Text(stringResource(R.string.mtu), fontStyle = FontStyle.Italic) + Text(text = mtu, modifier = Modifier.clickable { + clipboardManager.setText(AnnotatedString(mtu)) + }) + Box(modifier = Modifier.padding(10.dp)) + tunnel?.peers?.forEach{ + val peerKey = it.publicKey.toBase64().toString() + val allowedIps = it.allowedIps.joinToString() + val endpoint = if(it.endpoint.isPresent) it.endpoint.get().toString() else "None" + Text(stringResource(R.string.peer), fontWeight = FontWeight.Bold, fontSize = 20.sp) + Text(stringResource(R.string.public_key), fontStyle = FontStyle.Italic) + Text(text = peerKey, modifier = Modifier.clickable { + clipboardManager.setText(AnnotatedString(peerKey)) + }) + Text(stringResource(id = R.string.allowed_ips), fontStyle = FontStyle.Italic) + Text(text = allowedIps, modifier = Modifier.clickable { + clipboardManager.setText(AnnotatedString(allowedIps)) + }) + Text(stringResource(R.string.endpoint), fontStyle = FontStyle.Italic) + Text(text = endpoint, modifier = Modifier.clickable { + clipboardManager.setText(AnnotatedString(endpoint)) + }) + if (tunnelStats != null) { + val totalRx = tunnelStats?.totalRx() ?: 0 + val totalTx = tunnelStats?.totalTx() ?: 0 + if((totalRx + totalTx != 0L)) { + val rxKB = NumberUtils.bytesToKB(tunnelStats!!.totalRx()) + val txKB = NumberUtils.bytesToKB(tunnelStats!!.totalTx()) + Text(stringResource(R.string.transfer), fontStyle = FontStyle.Italic) + Text("rx: ${NumberUtils.formatDecimalTwoPlaces(rxKB)} KB tx: ${NumberUtils.formatDecimalTwoPlaces(txKB)} KB") + Text(stringResource(R.string.last_handshake), fontStyle = FontStyle.Italic) + val handshakeEpoch = lastHandshake[it.publicKey] + if(handshakeEpoch != null) { + if(handshakeEpoch == 0L) { + Text("Never") + } else { + val time = Instant.ofEpochMilli(handshakeEpoch) + Text("${Duration.between(time, Instant.now()).seconds} seconds ago") + } + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/detail/DetailViewModel.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/detail/DetailViewModel.kt new file mode 100644 index 0000000000..cf83878a0b --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/detail/DetailViewModel.kt @@ -0,0 +1,45 @@ +package net.nymtech.nymconnect.ui.screens.detail + +import androidx.lifecycle.ViewModel +import com.wireguard.config.Config +import net.nymtech.nymconnect.repository.Repository +import net.nymtech.nymconnect.service.tunnel.VpnService +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import timber.log.Timber +import javax.inject.Inject + +@HiltViewModel +class DetailViewModel @Inject constructor(private val tunnelRepo : Repository, private val vpnService : VpnService + +) : ViewModel() { + + private val _tunnel = MutableStateFlow(null) + val tunnel get() = _tunnel.asStateFlow() + + private val _tunnelName = MutableStateFlow("") + val tunnelName = _tunnelName.asStateFlow() + val tunnelStats get() = vpnService.statistics + val lastHandshake get() = vpnService.lastHandshake + + private var config : TunnelConfig? = null + + suspend fun getTunnelById(id : String?) : TunnelConfig? { + return try { + if(id != null) { + config = tunnelRepo.getById(id.toLong()) + if (config != null) { + _tunnel.emit(TunnelConfig.configFromQuick(config!!.wgQuick)) + _tunnelName.emit(config!!.name) + } + return config + } + return null + } catch (e : Exception) { + Timber.e(e.message) + null + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt new file mode 100644 index 0000000000..e2abdd07b7 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt @@ -0,0 +1,336 @@ +package net.nymtech.nymconnect.ui.screens.main + +import android.annotation.SuppressLint +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically +import androidx.compose.foundation.clickable +import androidx.compose.foundation.focusable +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.FileOpen +import androidx.compose.material.icons.rounded.Add +import androidx.compose.material.icons.rounded.Circle +import androidx.compose.material.icons.rounded.Delete +import androidx.compose.material.icons.rounded.Edit +import androidx.compose.material.icons.rounded.Info +import androidx.compose.material3.Divider +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.FabPosition +import androidx.compose.material3.FloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarDuration +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.SnackbarResult +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.hapticfeedback.HapticFeedbackType +import androidx.compose.ui.input.nestedscroll.NestedScrollConnection +import androidx.compose.ui.input.nestedscroll.NestedScrollSource +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalHapticFeedback +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.navigation.NavController +import com.wireguard.android.backend.Tunnel +import net.nymtech.nymconnect.R +import net.nymtech.nymconnect.WireGuardAutoTunnel +import net.nymtech.nymconnect.service.tunnel.HandshakeStatus +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig +import net.nymtech.nymconnect.ui.Routes +import net.nymtech.nymconnect.ui.common.RowListItem +import net.nymtech.nymconnect.ui.theme.brickRed +import net.nymtech.nymconnect.ui.theme.mint +import kotlinx.coroutines.launch + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun MainScreen( + viewModel: MainViewModel = hiltViewModel(), padding: PaddingValues, + snackbarHostState: SnackbarHostState, navController: NavController +) { + + val haptic = LocalHapticFeedback.current + val context = LocalContext.current + val isVisible = rememberSaveable { mutableStateOf(true) } + val scope = rememberCoroutineScope() + + val sheetState = rememberModalBottomSheetState() + var showBottomSheet by remember { mutableStateOf(false) } + val tunnels by viewModel.tunnels.collectAsStateWithLifecycle(mutableListOf()) + val handshakeStatus by viewModel.handshakeStatus.collectAsStateWithLifecycle(HandshakeStatus.NOT_STARTED) + val viewState = viewModel.viewState.collectAsStateWithLifecycle() + var selectedTunnel by remember { mutableStateOf(null) } + val state by viewModel.state.collectAsStateWithLifecycle(Tunnel.State.DOWN) + val tunnelName by viewModel.tunnelName.collectAsStateWithLifecycle("") + + // Nested scroll for control FAB + val nestedScrollConnection = remember { + object : NestedScrollConnection { + override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { + // Hide FAB + if (available.y < -1) { + isVisible.value = false + } + // Show FAB + if (available.y > 1) { + isVisible.value = true + } + return Offset.Zero + } + } + } + + LaunchedEffect(viewState.value) { + if (viewState.value.showSnackbarMessage) { + val result = snackbarHostState.showSnackbar( + message = viewState.value.snackbarMessage, + actionLabel = viewState.value.snackbarActionText, + duration = SnackbarDuration.Long, + ) + when (result) { + SnackbarResult.ActionPerformed -> viewState.value.onSnackbarActionClick + SnackbarResult.Dismissed -> viewState.value.onSnackbarActionClick + } + } + } + + val pickFileLauncher = rememberLauncherForActivityResult( + ActivityResultContracts.GetContent() + ) { file -> + if (file != null) { + viewModel.onTunnelFileSelected(file) + } + } + + Scaffold( + modifier = Modifier.pointerInput(Unit) { + detectTapGestures(onTap = { + selectedTunnel = null + }) + }, + floatingActionButtonPosition = FabPosition.End, + floatingActionButton = { + AnimatedVisibility( + visible = isVisible.value, + enter = slideInVertically(initialOffsetY = { it * 2 }), + exit = slideOutVertically(targetOffsetY = { it * 2 }), + ) { + FloatingActionButton( + modifier = Modifier.padding(bottom = 90.dp), + onClick = { + showBottomSheet = true + }, + containerColor = MaterialTheme.colorScheme.secondary, + shape = RoundedCornerShape(16.dp), + ) { + Icon( + imageVector = Icons.Rounded.Add, + contentDescription = stringResource(id = R.string.add_tunnel), + tint = Color.DarkGray, + ) + } + } + } + ) { + if (tunnels.isEmpty()) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxSize() + .padding(padding) + ) { + Text(text = stringResource(R.string.no_tunnels), fontStyle = FontStyle.Italic) + } + } + if (showBottomSheet) { + ModalBottomSheet( + onDismissRequest = { + showBottomSheet = false + }, + sheetState = sheetState + ) { + // Sheet content + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { + showBottomSheet = false + pickFileLauncher.launch("*/*") + } + .padding(10.dp) + ) { + Icon( + Icons.Filled.FileOpen, + contentDescription = stringResource(id = R.string.open_file), + modifier = Modifier.padding(10.dp) + ) + Text( + stringResource(id = R.string.add_from_file), + modifier = Modifier.padding(10.dp) + ) + } + Divider() + } + } + Column( + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.Top, + modifier = Modifier + .fillMaxSize() + .padding(padding) + ) { + + LazyColumn( + modifier = Modifier.fillMaxSize() + .nestedScroll(nestedScrollConnection), + ) { + itemsIndexed(tunnels.toList()) { index, tunnel -> + val focusRequester = FocusRequester(); + RowListItem(leadingIcon = Icons.Rounded.Circle, + leadingIconColor = if (tunnelName == tunnel.name) when (handshakeStatus) { + HandshakeStatus.HEALTHY -> mint + HandshakeStatus.UNHEALTHY -> brickRed + HandshakeStatus.NOT_STARTED -> Color.Gray + HandshakeStatus.NEVER_CONNECTED -> brickRed + } else Color.Gray, + text = tunnel.name, + onHold = { + if (state == Tunnel.State.UP && tunnel.name == tunnelName) { + scope.launch { + viewModel.showSnackBarMessage(context.resources.getString(R.string.turn_off_tunnel)) + } + return@RowListItem + } + haptic.performHapticFeedback(HapticFeedbackType.LongPress) + selectedTunnel = tunnel; + }, + onClick = { + if (!WireGuardAutoTunnel.isRunningOnAndroidTv(context)) { + navController.navigate("${Routes.Detail.name}/${tunnel.id}") + } else { + focusRequester.requestFocus() + } + }, + rowButton = { + if (tunnel.id == selectedTunnel?.id) { + Row { + IconButton(onClick = { + navController.navigate("${Routes.Config.name}/${selectedTunnel?.id}") + }) { + Icon(Icons.Rounded.Edit, stringResource(id = R.string.edit)) + } + IconButton( + modifier = Modifier.focusable(), + onClick = { viewModel.onDelete(tunnel) }) { + Icon( + Icons.Rounded.Delete, + stringResource(id = R.string.delete) + ) + } + } + } else { + if (WireGuardAutoTunnel.isRunningOnAndroidTv(context)) { + Row { + IconButton( + modifier = Modifier.focusRequester(focusRequester), + onClick = { + navController.navigate("${Routes.Detail.name}/${tunnel.id}") + }) { + Icon(Icons.Rounded.Info, "Info") + } + IconButton(onClick = { + if (state == Tunnel.State.UP && tunnel.name == tunnelName) + scope.launch { + viewModel.showSnackBarMessage( + context.resources.getString( + R.string.turn_off_tunnel + ) + ) + } else { + navController.navigate("${Routes.Config.name}/${tunnel.id}") + } + }) { + Icon( + Icons.Rounded.Edit, + stringResource(id = R.string.edit) + ) + } + IconButton(onClick = { + if (state == Tunnel.State.UP && tunnel.name == tunnelName) + scope.launch { + viewModel.showSnackBarMessage( + context.resources.getString( + R.string.turn_off_tunnel + ) + ) + } else { + viewModel.onDelete(tunnel) + } + }) { + Icon( + Icons.Rounded.Delete, + stringResource(id = R.string.delete) + ) + } + Switch( + checked = (state == Tunnel.State.UP && tunnel.name == tunnelName), + onCheckedChange = { checked -> + if (checked) viewModel.onTunnelStart(tunnel) else viewModel.onTunnelStop() + } + ) + } + } else { + Switch( + checked = (state == Tunnel.State.UP && tunnel.name == tunnelName), + onCheckedChange = { checked -> + if (checked) viewModel.onTunnelStart(tunnel) else viewModel.onTunnelStop() + } + ) + } + } + }) + } + } + } + } +} diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt new file mode 100644 index 0000000000..a88b5adcb9 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt @@ -0,0 +1,179 @@ +package net.nymtech.nymconnect.ui.screens.main + +import android.annotation.SuppressLint +import android.app.Application +import android.content.Context +import android.net.Uri +import android.provider.OpenableColumns +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.wireguard.config.BadConfigException +import com.wireguard.config.Config +import net.nymtech.nymconnect.R +import net.nymtech.nymconnect.repository.Repository +import net.nymtech.nymconnect.service.foreground.ServiceState +import net.nymtech.nymconnect.service.foreground.ServiceManager +import net.nymtech.nymconnect.service.foreground.WireGuardConnectivityWatcherService +import net.nymtech.nymconnect.service.shortcut.ShortcutsManager +import net.nymtech.nymconnect.service.tunnel.VpnService +import net.nymtech.nymconnect.service.tunnel.model.Settings +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig +import net.nymtech.nymconnect.ui.ViewState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import timber.log.Timber +import javax.inject.Inject + + +@HiltViewModel +class MainViewModel @Inject constructor(private val application : Application, + private val tunnelRepo : Repository, + private val settingsRepo : Repository, + private val vpnService: VpnService, +) : ViewModel() { + + private val _viewState = MutableStateFlow(ViewState()) + val viewState get() = _viewState.asStateFlow() + val tunnels get() = tunnelRepo.itemFlow + val state get() = vpnService.state + + val handshakeStatus get() = vpnService.handshakeStatus + val tunnelName get() = vpnService.tunnelName + private val _settings = MutableStateFlow(Settings()) + val settings get() = _settings.asStateFlow() + + private val defaultConfigName = { + "tunnel${(Math.random() * 100000).toInt()}" + } + + + init { + viewModelScope.launch { + settingsRepo.itemFlow.collect { + val settings = it.first() + validateWatcherServiceState(settings) + _settings.emit(settings) + } + } + } + + private fun validateWatcherServiceState(settings: Settings) { + val watcherState = ServiceManager.getServiceState(application.applicationContext, WireGuardConnectivityWatcherService::class.java) + if(settings.isAutoTunnelEnabled && watcherState == ServiceState.STOPPED && settings.defaultTunnel != null) { + ServiceManager.startWatcherService(application.applicationContext, settings.defaultTunnel!!) + } + } + + + fun onDelete(tunnel : TunnelConfig) { + viewModelScope.launch { + if(tunnelRepo.count() == 1L) { + ServiceManager.stopWatcherService(application.applicationContext) + val settings = settingsRepo.getAll() + if(!settings.isNullOrEmpty()) { + val setting = settings[0] + setting.defaultTunnel = null + setting.isAutoTunnelEnabled = false + setting.isAlwaysOnVpnEnabled = false + settingsRepo.save(setting) + } + } + tunnelRepo.delete(tunnel) + ShortcutsManager.removeTunnelShortcuts(application.applicationContext, tunnel) + } + } + + fun onTunnelStart(tunnelConfig : TunnelConfig) = viewModelScope.launch { + ServiceManager.startVpnService(application.applicationContext, tunnelConfig.toString()) + } + + fun onTunnelStop() { + ServiceManager.stopVpnService(application.applicationContext) + } + + fun onTunnelFileSelected(uri : Uri) { + try { + val fileName = getFileName(application.applicationContext, uri) + val extension = getFileExtensionFromFileName(fileName) + if(extension != ".conf") { + viewModelScope.launch { + showSnackBarMessage(application.resources.getString(R.string.file_extension_message)) + } + return + } + val stream = application.applicationContext.contentResolver.openInputStream(uri) + stream ?: return + val bufferReader = stream.bufferedReader(charset = Charsets.UTF_8) + val config = Config.parse(bufferReader) + val tunnelName = getNameFromFileName(fileName) + saveTunnel(TunnelConfig(name = tunnelName, wgQuick = config.toWgQuickString())) + stream.close() + } catch(_: BadConfigException) { + viewModelScope.launch { + showSnackBarMessage(application.applicationContext.getString(R.string.bad_config)) + } + } + } + + private fun saveTunnel(tunnelConfig : TunnelConfig) { + viewModelScope.launch { + tunnelRepo.save(tunnelConfig) + ShortcutsManager.createTunnelShortcuts(application.applicationContext, tunnelConfig) + } + } + + @SuppressLint("Range") + private fun getFileName(context: Context, uri: Uri): String { + if (uri.scheme == "content") { + val cursor = try { + context.contentResolver.query(uri, null, null, null, null) + } catch (e : Exception) { + Timber.d("Exception getting config name") + null + } + cursor ?: return defaultConfigName() + cursor.use { + if(cursor.moveToFirst()) { + return cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)) + } + } + } + return defaultConfigName() + } + + suspend fun showSnackBarMessage(message : String) { + _viewState.emit(_viewState.value.copy( + showSnackbarMessage = true, + snackbarMessage = message, + snackbarActionText = "Okay", + onSnackbarActionClick = { + viewModelScope.launch { + dismissSnackBar() + } + } + )) + delay(3000) + dismissSnackBar() + } + + private suspend fun dismissSnackBar() { + _viewState.emit(_viewState.value.copy( + showSnackbarMessage = false + )) + } + + private fun getNameFromFileName(fileName : String) : String { + return fileName.substring(0 , fileName.lastIndexOf('.') ) + } + + private fun getFileExtensionFromFileName(fileName : String) : String { + return try { + fileName.substring(fileName.lastIndexOf('.')) + } catch (e : Exception) { + "" + } + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt new file mode 100644 index 0000000000..4616a8fd9a --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt @@ -0,0 +1,415 @@ +package net.nymtech.nymconnect.ui.screens.settings + +import android.Manifest +import android.content.Intent +import android.net.Uri +import android.os.Build +import android.provider.Settings +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.outlined.Add +import androidx.compose.material.icons.rounded.LocationOff +import androidx.compose.material3.Button +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExposedDropdownMenuBox +import androidx.compose.material3.ExposedDropdownMenuDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.SnackbarDuration +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.SnackbarResult +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardCapitalization +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.navigation.NavController +import com.google.accompanist.permissions.ExperimentalPermissionsApi +import com.google.accompanist.permissions.isGranted +import com.google.accompanist.permissions.rememberPermissionState +import net.nymtech.nymconnect.R +import net.nymtech.nymconnect.WireGuardAutoTunnel +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig +import net.nymtech.nymconnect.ui.Routes +import net.nymtech.nymconnect.ui.common.ClickableIconButton +import kotlinx.coroutines.launch + +@OptIn(ExperimentalMaterial3Api::class, ExperimentalPermissionsApi::class, + ExperimentalLayoutApi::class +) +@Composable +fun SettingsScreen( + viewModel: SettingsViewModel = hiltViewModel(), + padding: PaddingValues, + navController: NavController, + focusRequester: FocusRequester, + snackbarHostState: SnackbarHostState = remember { SnackbarHostState() } +) { + + val scope = rememberCoroutineScope() + val context = LocalContext.current + val focusManager = LocalFocusManager.current + val interactionSource = remember { MutableInteractionSource() } + + var expanded by remember { mutableStateOf(false) } + val viewState by viewModel.viewState.collectAsStateWithLifecycle() + val settings by viewModel.settings.collectAsStateWithLifecycle() + val trustedSSIDs by viewModel.trustedSSIDs.collectAsStateWithLifecycle() + val tunnels by viewModel.tunnels.collectAsStateWithLifecycle(mutableListOf()) + val backgroundLocationState = + rememberPermissionState(Manifest.permission.ACCESS_BACKGROUND_LOCATION) + val fineLocationState = rememberPermissionState(Manifest.permission.ACCESS_FINE_LOCATION) + var currentText by remember { mutableStateOf("") } + val scrollState = rememberScrollState() + var isLocationServicesEnabled by remember { mutableStateOf(viewModel.checkLocationServicesEnabled())} + + LaunchedEffect(viewState) { + if (viewState.showSnackbarMessage) { + val result = snackbarHostState.showSnackbar( + message = viewState.snackbarMessage, + actionLabel = viewState.snackbarActionText, + duration = SnackbarDuration.Long, + ) + when (result) { + SnackbarResult.ActionPerformed -> viewState.onSnackbarActionClick + SnackbarResult.Dismissed -> viewState.onSnackbarActionClick + } + } + } + + fun saveTrustedSSID() { + if (currentText.isNotEmpty()) { + scope.launch { + viewModel.onSaveTrustedSSID(currentText) + currentText = "" + } + } + } + + fun openSettings() { + scope.launch { + val intentSettings = + Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) + intentSettings.data = + Uri.fromParts("package", context.packageName, null) + context.startActivity(intentSettings) + } + } + + if(!backgroundLocationState.status.isGranted && Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { + Column(horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Top, + modifier = Modifier + .fillMaxSize() + .verticalScroll(scrollState) + .padding(padding)) { + Icon(Icons.Rounded.LocationOff, contentDescription = stringResource(id = R.string.map), modifier = Modifier + .padding(30.dp) + .size(128.dp)) + Text(stringResource(R.string.prominent_background_location_title), textAlign = TextAlign.Center, modifier = Modifier.padding(30.dp), fontSize = 20.sp) + Text(stringResource(R.string.prominent_background_location_message), textAlign = TextAlign.Center, modifier = Modifier.padding(30.dp), fontSize = 15.sp) + Row( + modifier = if(WireGuardAutoTunnel.isRunningOnAndroidTv(context)) Modifier + .fillMaxWidth() + .padding(10.dp) else Modifier + .fillMaxWidth() + .padding(30.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly + ) { + Button(onClick = { + navController.navigate(Routes.Main.name) + }) { + Text(stringResource(id = R.string.no_thanks)) + } + Button(modifier = Modifier.focusRequester(focusRequester), onClick = { + openSettings() + }) { + Text(stringResource(id = R.string.turn_on)) + } + } + } + return + } + + if(!fineLocationState.status.isGranted) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxSize() + .padding(padding) + ) { + Text( + stringResource(id = R.string.precise_location_message), + textAlign = TextAlign.Center, + modifier = Modifier.padding(15.dp), + fontStyle = FontStyle.Italic + ) + Button(modifier = Modifier.focusRequester(focusRequester),onClick = { + fineLocationState.launchPermissionRequest() + }) { + Text(stringResource(id = R.string.request)) + } + + } + return + } + + if (tunnels.isEmpty()) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxSize() + .padding(padding) + ) { + Text( + stringResource(R.string.one_tunnel_required), + textAlign = TextAlign.Center, + modifier = Modifier.padding(15.dp), + fontStyle = FontStyle.Italic + ) + } + return + } + if(!isLocationServicesEnabled && Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxSize() + .padding(padding) + ) { + Text( + stringResource(id = R.string.location_services_not_detected), + textAlign = TextAlign.Center, + modifier = Modifier.padding(15.dp), + fontStyle = FontStyle.Italic + ) + Button(modifier = Modifier.focusRequester(focusRequester), onClick = { + val locationServicesEnabled = viewModel.checkLocationServicesEnabled() + isLocationServicesEnabled = locationServicesEnabled + if(!locationServicesEnabled) { + scope.launch { + viewModel.showSnackBarMessage(context.getString(R.string.detecting_location_services_disabled)) + } + } + }) { + Text(stringResource(id = R.string.check_again)) + } + } + return + } + val screenPadding = if(WireGuardAutoTunnel.isRunningOnAndroidTv(context)) 5.dp else 15.dp + Column( + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.Top, + modifier = if(WireGuardAutoTunnel.isRunningOnAndroidTv(context)) Modifier + .fillMaxHeight(.85f) + .fillMaxWidth() + .verticalScroll(scrollState) + .clickable(indication = null, interactionSource = interactionSource) { + focusManager.clearFocus() + } + .padding(padding) else Modifier + .fillMaxSize() + .verticalScroll(scrollState) + .clickable(indication = null, interactionSource = interactionSource) { + focusManager.clearFocus() + } + .padding(padding) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(screenPadding), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text(stringResource(R.string.enable_auto_tunnel)) + Switch( + modifier = Modifier.focusRequester(focusRequester), + enabled = !settings.isAlwaysOnVpnEnabled, + checked = settings.isAutoTunnelEnabled, + onCheckedChange = { + scope.launch { + viewModel.toggleAutoTunnel() + } + } + ) + } + Text( + stringResource(id = R.string.select_tunnel), + textAlign = TextAlign.Center, + modifier = Modifier.padding(screenPadding, bottom = 5.dp, top = 5.dp) + ) + ExposedDropdownMenuBox( + expanded = expanded, + onExpandedChange = { + if(!(settings.isAutoTunnelEnabled || settings.isAlwaysOnVpnEnabled)) { + expanded = !expanded }}, + modifier = Modifier.padding(start = 15.dp, top = 5.dp, bottom = 10.dp).clickable { + expanded = !expanded + }, + ) { + TextField( + enabled = !(settings.isAutoTunnelEnabled || settings.isAlwaysOnVpnEnabled), + value = settings.defaultTunnel?.let { + TunnelConfig.from(it).name } + ?: "", + readOnly = true, + modifier = Modifier.menuAnchor(), + label = { Text(stringResource(R.string.tunnels)) }, + onValueChange = { }, + trailingIcon = { + ExposedDropdownMenuDefaults.TrailingIcon( + expanded = expanded + ) + } + ) + ExposedDropdownMenu( + expanded = expanded, + onDismissRequest = { + expanded = false + } + ) { + tunnels.forEach() { tunnel -> + DropdownMenuItem( + onClick = { + scope.launch { + viewModel.onDefaultTunnelSelected(tunnel) + } + expanded = false + }, + text = { Text(text = tunnel.name) } + ) + } + } + } + Text( + stringResource(R.string.trusted_ssid), + textAlign = TextAlign.Center, + modifier = Modifier.padding(screenPadding, bottom = 5.dp, top = 5.dp) + ) + FlowRow( + modifier = Modifier.padding(screenPadding), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalArrangement = Arrangement.SpaceEvenly + ) { + trustedSSIDs.forEach { ssid -> + ClickableIconButton(onIconClick = { + scope.launch { + viewModel.onDeleteTrustedSSID(ssid) + } + }, text = ssid, icon = Icons.Filled.Close, enabled = !(settings.isAutoTunnelEnabled || settings.isAlwaysOnVpnEnabled)) + } + } + OutlinedTextField( + enabled = !(settings.isAutoTunnelEnabled || settings.isAlwaysOnVpnEnabled), + value = currentText, + onValueChange = { currentText = it }, + label = { Text(stringResource(R.string.add_trusted_ssid)) }, + modifier = Modifier.padding(start = screenPadding, top = 5.dp), + maxLines = 1, + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.None, + imeAction = ImeAction.Done + ), + keyboardActions = KeyboardActions( + onDone = { + saveTrustedSSID() + } + ), + trailingIcon = { + IconButton(onClick = { saveTrustedSSID() }) { + Icon( + imageVector = Icons.Outlined.Add, + contentDescription = if (currentText == "") stringResource(id = R.string.trusted_ssid_empty_description) else stringResource( + id = R.string.trusted_ssid_value_description + ), + tint = if(currentText == "") Color.Transparent else Color.Green + ) + } + }, + ) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(screenPadding), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text(stringResource(R.string.tunnel_mobile_data)) + Switch( + enabled = !(settings.isAutoTunnelEnabled || settings.isAlwaysOnVpnEnabled), + checked = settings.isTunnelOnMobileDataEnabled, + onCheckedChange = { + scope.launch { + viewModel.onToggleTunnelOnMobileData() + } + } + ) + } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(screenPadding), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text(stringResource(R.string.always_on_vpn_support)) + Switch( + enabled = !settings.isAutoTunnelEnabled, + checked = settings.isAlwaysOnVpnEnabled, + onCheckedChange = { + scope.launch { + viewModel.onToggleAlwaysOnVPN() + } + } + ) + } + } +} + + diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsViewModel.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsViewModel.kt new file mode 100644 index 0000000000..7143c1b4b6 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsViewModel.kt @@ -0,0 +1,124 @@ +package net.nymtech.nymconnect.ui.screens.settings + +import android.app.Application +import android.content.Context +import android.location.LocationManager +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import net.nymtech.nymconnect.R +import net.nymtech.nymconnect.repository.Repository +import net.nymtech.nymconnect.service.foreground.ServiceManager +import net.nymtech.nymconnect.service.tunnel.model.Settings +import net.nymtech.nymconnect.service.tunnel.model.TunnelConfig +import net.nymtech.nymconnect.ui.ViewState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + + +@HiltViewModel +class SettingsViewModel @Inject constructor(private val application : Application, + private val tunnelRepo : Repository, private val settingsRepo : Repository +) : ViewModel() { + + private val _trustedSSIDs = MutableStateFlow(emptyList()) + val trustedSSIDs = _trustedSSIDs.asStateFlow() + private val _settings = MutableStateFlow(Settings()) + val settings get() = _settings.asStateFlow() + val tunnels get() = tunnelRepo.itemFlow + private val _viewState = MutableStateFlow(ViewState()) + val viewState get() = _viewState.asStateFlow() + + init { + checkLocationServicesEnabled() + viewModelScope.launch { + settingsRepo.itemFlow.collect { + val settings = it.first() + _settings.emit(settings) + _trustedSSIDs.emit(settings.trustedNetworkSSIDs.toList()) + } + } + } + + suspend fun onSaveTrustedSSID(ssid: String) { + val trimmed = ssid.trim() + if (!_settings.value.trustedNetworkSSIDs.contains(trimmed)) { + _settings.value.trustedNetworkSSIDs.add(trimmed) + settingsRepo.save(_settings.value) + } else { + showSnackBarMessage("SSID already exists.") + } + } + + suspend fun onDefaultTunnelSelected(tunnelConfig: TunnelConfig) { + settingsRepo.save(_settings.value.copy( + defaultTunnel = tunnelConfig.toString() + )) + } + + suspend fun onToggleTunnelOnMobileData() { + settingsRepo.save(_settings.value.copy( + isTunnelOnMobileDataEnabled = !_settings.value.isTunnelOnMobileDataEnabled + )) + } + + suspend fun onDeleteTrustedSSID(ssid: String) { + _settings.value.trustedNetworkSSIDs.remove(ssid) + settingsRepo.save(_settings.value) + } + + suspend fun toggleAutoTunnel() { + if(_settings.value.defaultTunnel.isNullOrEmpty() && !_settings.value.isAutoTunnelEnabled) { + showSnackBarMessage(application.getString(R.string.select_tunnel_message)) + return + } + if(_settings.value.isAutoTunnelEnabled) { + ServiceManager.stopWatcherService(application) + } else { + if(_settings.value.defaultTunnel != null) { + val defaultTunnel = _settings.value.defaultTunnel + ServiceManager.startWatcherService(application, defaultTunnel!!) + } + } + settingsRepo.save(_settings.value.copy( + isAutoTunnelEnabled = !_settings.value.isAutoTunnelEnabled + )) + } + + suspend fun showSnackBarMessage(message : String) { + _viewState.emit(_viewState.value.copy( + showSnackbarMessage = true, + snackbarMessage = message, + snackbarActionText = "Okay", + onSnackbarActionClick = { + viewModelScope.launch { + dismissSnackBar() + } + } + )) + } + + private suspend fun dismissSnackBar() { + _viewState.emit(_viewState.value.copy( + showSnackbarMessage = false + )) + } + + suspend fun onToggleAlwaysOnVPN() { + if(_settings.value.defaultTunnel != null) { + _settings.emit( + _settings.value.copy(isAlwaysOnVpnEnabled = !_settings.value.isAlwaysOnVpnEnabled) + ) + settingsRepo.save(_settings.value) + } else { + showSnackBarMessage(application.getString(R.string.select_tunnel_message)) + } + } + fun checkLocationServicesEnabled() : Boolean { + val locationManager = + application.getSystemService(Context.LOCATION_SERVICE) as LocationManager + return locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/support/SupportScreen.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/support/SupportScreen.kt new file mode 100644 index 0000000000..31fc9dbf6a --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/support/SupportScreen.kt @@ -0,0 +1,83 @@ +package net.nymtech.nymconnect.ui.screens.support + +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import androidx.compose.foundation.clickable +import androidx.compose.foundation.focusable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import net.nymtech.nymconnect.R + +@Composable +fun SupportScreen(padding : PaddingValues, focusRequester: FocusRequester) { + + val context = LocalContext.current + + fun openWebPage(url: String) { + val webpage: Uri = Uri.parse(url) + val intent = Intent(Intent.ACTION_VIEW, webpage) + context.startActivity(intent) + } + + Column(horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Top, + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .focusable() + .padding(padding)) { + Text(stringResource(R.string.support_text), textAlign = TextAlign.Center, modifier = Modifier.padding(30.dp), fontSize = 15.sp) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(14.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly + ) { + IconButton(onClick = { + openWebPage(context.resources.getString(R.string.discord_url)) + }) { + Icon(imageVector = ImageVector.vectorResource(R.drawable.discord), "Discord") + } + IconButton(modifier = Modifier.focusRequester(focusRequester),onClick = { + openWebPage(context.resources.getString(R.string.github_url)) + }) { + Icon(imageVector = ImageVector.vectorResource(R.drawable.github), "Github") + } + } + Spacer(modifier = Modifier.weight(1f)) + Text(stringResource(id = R.string.privacy_policy), style = TextStyle(textDecoration = TextDecoration.Underline), + modifier = Modifier.clickable { + openWebPage(context.resources.getString(R.string.privacy_policy_url)) + }) + Text("App version: ${net.nymtech.nymconnect.BuildConfig.VERSION_NAME}", Modifier.padding(25.dp)) + } + } \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/theme/Color.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/theme/Color.kt new file mode 100644 index 0000000000..3561a75512 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/theme/Color.kt @@ -0,0 +1,17 @@ +package net.nymtech.nymconnect.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFF492532) +val virdigris = Color(0xFF5BC0BE) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFFFFFFFF) + +//status colors +val brickRed = Color(0xFFCE4257) +val pinkRed = Color(0xFFEF476F) +val mint = Color(0xFF52B788) diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/theme/Theme.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/theme/Theme.kt new file mode 100644 index 0000000000..647ad9f2ad --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/theme/Theme.kt @@ -0,0 +1,80 @@ +package net.nymtech.nymconnect.ui.theme + +import android.app.Activity +import android.os.Build +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat + +private val DarkColorScheme = darkColorScheme( + //primary = Purple80, + primary = virdigris, + secondary = virdigris, + // secondary = PurpleGrey80, + tertiary = virdigris + //tertiary = Pink80 +) + +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ +) + +@Composable +fun WireguardAutoTunnelTheme( + //force dark theme + darkTheme : Boolean = true, + //darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + //turning off dynamic color for now + dynamicColor: Boolean = false, + content: @Composable () -> Unit +) { + + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + WindowCompat.setDecorFitsSystemWindows(window, false) + window.statusBarColor = Color.Transparent.toArgb() + window.navigationBarColor = Color.Transparent.toArgb() + WindowCompat.getInsetsController(window, window.decorView).isAppearanceLightStatusBars = !darkTheme + WindowCompat.getInsetsController(window, window.decorView).isAppearanceLightNavigationBars = !darkTheme + } + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/theme/TransparentSystemBars.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/theme/TransparentSystemBars.kt new file mode 100644 index 0000000000..6a1c35331c --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/theme/TransparentSystemBars.kt @@ -0,0 +1,22 @@ +package net.nymtech.nymconnect.ui.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.ui.graphics.Color +import com.google.accompanist.systemuicontroller.rememberSystemUiController + +@Composable +fun TransparentSystemBars() { + val systemUiController = rememberSystemUiController() + val useDarkIcons = !isSystemInDarkTheme() + + DisposableEffect(systemUiController, useDarkIcons) { + systemUiController.setSystemBarsColor( + color = Color.Transparent, + darkIcons = useDarkIcons + ) + + onDispose {} + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/theme/Type.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/theme/Type.kt new file mode 100644 index 0000000000..6b89a8e327 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/theme/Type.kt @@ -0,0 +1,34 @@ +package net.nymtech.nymconnect.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ +) \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/NumberUtils.kt b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/NumberUtils.kt new file mode 100644 index 0000000000..aa240e6eb2 --- /dev/null +++ b/nym-vpn/android/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/NumberUtils.kt @@ -0,0 +1,25 @@ +package net.nymtech.nymconnect.util + +import java.math.BigDecimal +import java.text.DecimalFormat +import java.time.Duration +import java.time.Instant + +object NumberUtils { + + private const val BYTES_IN_KB = 1024L + + fun bytesToKB(bytes : Long) : BigDecimal { + return bytes.toBigDecimal().divide(BYTES_IN_KB.toBigDecimal()) + } + + fun formatDecimalTwoPlaces(bigDecimal: BigDecimal) : String { + val df = DecimalFormat("#.##") + return df.format(bigDecimal) + } + + fun getSecondsBetweenTimestampAndNow(epoch : Long) : Long { + val time = Instant.ofEpochMilli(epoch) + return Duration.between(time, Instant.now()).seconds + } +} \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/nym-vpn/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000000..2b068d1146 --- /dev/null +++ b/nym-vpn/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/res/drawable/discord.xml b/nym-vpn/android/app/src/main/res/drawable/discord.xml new file mode 100644 index 0000000000..df43339353 --- /dev/null +++ b/nym-vpn/android/app/src/main/res/drawable/discord.xml @@ -0,0 +1,10 @@ + + + diff --git a/nym-vpn/android/app/src/main/res/drawable/github.xml b/nym-vpn/android/app/src/main/res/drawable/github.xml new file mode 100644 index 0000000000..32f8254ebe --- /dev/null +++ b/nym-vpn/android/app/src/main/res/drawable/github.xml @@ -0,0 +1,12 @@ + + + diff --git a/nym-vpn/android/app/src/main/res/drawable/ic_launcher_background.xml b/nym-vpn/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000..07d5da9cbf --- /dev/null +++ b/nym-vpn/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nym-vpn/android/app/src/main/res/drawable/ic_launcher_foreground.xml b/nym-vpn/android/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000000..2b068d1146 --- /dev/null +++ b/nym-vpn/android/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/res/drawable/shield.xml b/nym-vpn/android/app/src/main/res/drawable/shield.xml new file mode 100644 index 0000000000..e49a1f265d --- /dev/null +++ b/nym-vpn/android/app/src/main/res/drawable/shield.xml @@ -0,0 +1,5 @@ + + + diff --git a/nym-vpn/android/app/src/main/res/drawable/vpn_off.xml b/nym-vpn/android/app/src/main/res/drawable/vpn_off.xml new file mode 100644 index 0000000000..d33949b74b --- /dev/null +++ b/nym-vpn/android/app/src/main/res/drawable/vpn_off.xml @@ -0,0 +1,5 @@ + + + diff --git a/nym-vpn/android/app/src/main/res/drawable/vpn_on.xml b/nym-vpn/android/app/src/main/res/drawable/vpn_on.xml new file mode 100644 index 0000000000..1339fb3b8b --- /dev/null +++ b/nym-vpn/android/app/src/main/res/drawable/vpn_on.xml @@ -0,0 +1,5 @@ + + + diff --git a/nym-vpn/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/nym-vpn/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/nym-vpn/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/nym-vpn/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/nym-vpn/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/nym-vpn/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000..4974445c9a Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/nym-vpn/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000..483ace7edf Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/nym-vpn/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000..59b2f1db44 Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/nym-vpn/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000..307fb6aab9 Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/nym-vpn/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000..e634763b42 Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/nym-vpn/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000..37a8d502c8 Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/nym-vpn/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000..5b412e78a0 Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/nym-vpn/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000..580c767c54 Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/nym-vpn/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000..51a588fdee Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/nym-vpn/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000..65cefcb196 Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/nym-vpn/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000..312d818bbe Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/nym-vpn/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000..5070e583a0 Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/nym-vpn/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000..18252905f8 Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/nym-vpn/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000..514ec36652 Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/nym-vpn/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/nym-vpn/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000..83e115a87d Binary files /dev/null and b/nym-vpn/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/nym-vpn/android/app/src/main/res/values/colors.xml b/nym-vpn/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000000..d035176a0b --- /dev/null +++ b/nym-vpn/android/app/src/main/res/values/colors.xml @@ -0,0 +1,11 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF1c1b20 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/res/values/ic_banner_background.xml b/nym-vpn/android/app/src/main/res/values/ic_banner_background.xml new file mode 100644 index 0000000000..5274b8a4f3 --- /dev/null +++ b/nym-vpn/android/app/src/main/res/values/ic_banner_background.xml @@ -0,0 +1,4 @@ + + + #121212 + \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/res/values/ic_launcher_background.xml b/nym-vpn/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000000..a3b9258141 --- /dev/null +++ b/nym-vpn/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #1D2125 + \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/res/values/strings.xml b/nym-vpn/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000000..2c1d791d4d --- /dev/null +++ b/nym-vpn/android/app/src/main/res/values/strings.xml @@ -0,0 +1,90 @@ + + NymConnect + tunnelConfig + VPN Channel + VPN Notification Channel + Watcher Channel + Watcher Notification Channel + FOREGROUND_FILE + https://github.com/nymtech/nym + https://github.com/nymtech/nym + File is not a .conf file + Turn off tunnel before editing + No tunnels added yet! + Tunnel name already exists + https://discord.com/invite/nym + Watcher Service + Monitoring network state changes + VPN Connected + Connected to tunnel - + VPN permission is required for the app to work properly. If this permission is not launching, please disable \"Always-on VPN\" in your phone settings for the official WireGuard mobile app and try again. + Notifications permission is required for the app to work properly. + Open Settings + Add Trusted SSID + Trusted SSID + Tunnels + Select Tunnel + Enable auto tunneling + Tunnel on mobile data + \"Allow all the time\" location permission is required for retrieving Wi-Fi SSID in the background. Permission is needed for this feature. + Location permission is required for this feature to work properly. + At least one tunnel required to use this feature + "Retry" + View Privacy Policy + Okay + This feature requires background location permission to enable Wi-Fi SSID monitoring even while the application is closed. For more details, please see the Privacy Policy linked on the Support screen. + Background Location Disclosure + TODO + Enter SSID + Submit SSID + [Interface] + Add tunnel from files + File Open + Tunnel Edit + Tunnel Name + Edit + Delete + Add Tunnel + Exclude + Include + Tunnel all applications + Configuration changes saved. + Save changes + Icon + No thanks + Turn on + Map + Bad config. Please try again. + Interface + Public key + Waiting for the Barcode UI module to be downloaded. + Barcode module downloading. Try again. + Addresses + DNS servers + MTU + Peer + Allowed IPs + Endpoint + Transfer + Last handshake + Name + Restart Tunnel + VPN Connection Failed + Failed connection to - + Attempting to connect to server after 30 seconds of no response. + Attempting to reconnect to server after more than one minute of no response. + Enable Always-On VPN support + Please select a tunnel first + Unable to detect Location Services which are required for this feature. Please enable Location Services. + Check again + Detecting Location Services disabled + This feature requires precise location to access Wi-Fi SSID name. Please enable precise location here or in the app settings. + Request + Toggle VPN + No tunnels available + Search packages + Clear Icon + Search Icon + Attempting connection.. + VPN Starting + \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/res/values/themes.xml b/nym-vpn/android/app/src/main/res/values/themes.xml new file mode 100644 index 0000000000..9414a536e4 --- /dev/null +++ b/nym-vpn/android/app/src/main/res/values/themes.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/res/xml/backup_rules.xml b/nym-vpn/android/app/src/main/res/xml/backup_rules.xml new file mode 100644 index 0000000000..fa0f996d2c --- /dev/null +++ b/nym-vpn/android/app/src/main/res/xml/backup_rules.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/nym-vpn/android/app/src/main/res/xml/data_extraction_rules.xml b/nym-vpn/android/app/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 0000000000..9ee9997b0b --- /dev/null +++ b/nym-vpn/android/app/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/nym-vpn/android/app/src/test/java/com/zaneschepke/wireguardautotunnel/ExampleUnitTest.kt b/nym-vpn/android/app/src/test/java/com/zaneschepke/wireguardautotunnel/ExampleUnitTest.kt new file mode 100644 index 0000000000..c3453e018c --- /dev/null +++ b/nym-vpn/android/app/src/test/java/com/zaneschepke/wireguardautotunnel/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package net.nymtech.nymconnect + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/nym-vpn/android/build.gradle.kts b/nym-vpn/android/build.gradle.kts new file mode 100644 index 0000000000..1a6937f39a --- /dev/null +++ b/nym-vpn/android/build.gradle.kts @@ -0,0 +1,19 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + val objectBoxVersion by extra("3.5.1") + val hiltVersion by extra("2.47") + val accompanistVersion by extra("0.31.2-alpha") + + dependencies { + classpath("io.objectbox:objectbox-gradle-plugin:$objectBoxVersion") + classpath("com.google.gms:google-services:4.3.15") + } +} + +plugins { + id("com.android.application") version "8.2.0-beta02" apply false + id("org.jetbrains.kotlin.android") version "1.8.22" apply false + id("com.google.dagger.hilt.android") version "2.44" apply false + kotlin("plugin.serialization") version "1.8.22" apply false +} diff --git a/nym-vpn/android/gradle.properties b/nym-vpn/android/gradle.properties new file mode 100644 index 0000000000..1023be831f --- /dev/null +++ b/nym-vpn/android/gradle.properties @@ -0,0 +1,25 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true +#enable buildconfig values +android.defaults.buildfeatures.buildconfig=true \ No newline at end of file diff --git a/nym-vpn/android/gradle/wrapper/gradle-wrapper.jar b/nym-vpn/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..e708b1c023 Binary files /dev/null and b/nym-vpn/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/nym-vpn/android/gradle/wrapper/gradle-wrapper.properties b/nym-vpn/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..96f2e7a959 --- /dev/null +++ b/nym-vpn/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Apr 24 22:46:45 EDT 2023 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/nym-vpn/android/gradlew b/nym-vpn/android/gradlew new file mode 100755 index 0000000000..4f906e0c81 --- /dev/null +++ b/nym-vpn/android/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/nym-vpn/android/gradlew.bat b/nym-vpn/android/gradlew.bat new file mode 100644 index 0000000000..107acd32c4 --- /dev/null +++ b/nym-vpn/android/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/nym-vpn/android/settings.gradle.kts b/nym-vpn/android/settings.gradle.kts new file mode 100644 index 0000000000..aaebe93cd6 --- /dev/null +++ b/nym-vpn/android/settings.gradle.kts @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "NymConnect" +include(":app") + \ No newline at end of file diff --git a/clients/webassembly/.cargo-ok b/nym-vpn/ios/.gitkeep similarity index 100% rename from clients/webassembly/.cargo-ok rename to nym-vpn/ios/.gitkeep diff --git a/nym-vpn/linux/.gitkeep b/nym-vpn/linux/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nym-vpn/macos/.gitkeep b/nym-vpn/macos/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nym-vpn/win/.gitkeep b/nym-vpn/win/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/nym-wallet/package.json b/nym-wallet/package.json index 498c3bafe5..308bd4f63a 100644 --- a/nym-wallet/package.json +++ b/nym-wallet/package.json @@ -31,7 +31,7 @@ "@nymproject/mui-theme": "^1.0.0", "@nymproject/react": "^1.0.0", "@nymproject/types": "^1.0.0", - "@nymproject/sdk": "^1.1.8", + "@nymproject/node-tester": ">=1.2.0-rc.1 || ^1", "@storybook/react": "^6.5.15", "@tauri-apps/api": "^1.2.0", "@tauri-apps/tauri-forage": "^1.0.0-beta.2", @@ -123,4 +123,4 @@ "webpack-favicons": "^1.3.8", "webpack-merge": "^5.8.0" } -} \ No newline at end of file +} diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index cb3548ca59..a7145c9282 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -19,7 +19,7 @@ tauri-codegen = "=1.2.1" tauri-macros = "=1.2.1" [dependencies] -async-trait = "0.1.64" +async-trait = "0.1.68" bip39 = { version = "2.0.0", features = ["zeroize", "rand"] } cfg-if = "1.0.0" colored = "2.0" diff --git a/nym-wallet/src/components/Bonding/Bond.tsx b/nym-wallet/src/components/Bonding/Bond.tsx index 8cf745c6e5..304543cd51 100644 --- a/nym-wallet/src/components/Bonding/Bond.tsx +++ b/nym-wallet/src/components/Bonding/Bond.tsx @@ -21,7 +21,7 @@ export const Bond = ({ > Bond a mix node or a gateway. Learn how to set up and run a node{' '} - + here diff --git a/nym-wallet/src/components/TestNode/Packets.tsx b/nym-wallet/src/components/TestNode/Packets.tsx index dfbc4d7144..e935f26960 100644 --- a/nym-wallet/src/components/TestNode/Packets.tsx +++ b/nym-wallet/src/components/TestNode/Packets.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { TestStatus } from '@nymproject/sdk'; import { Divider, Typography } from '@mui/material'; +import { TestStatus } from './types'; import { ResultsCard, ResultsCardDetail } from './ResultsCard'; export const Packets = ({ diff --git a/nym-wallet/src/components/TestNode/Results.tsx b/nym-wallet/src/components/TestNode/Results.tsx index 58856801b3..15404dde1c 100644 --- a/nym-wallet/src/components/TestNode/Results.tsx +++ b/nym-wallet/src/components/TestNode/Results.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { TestStatus } from '@nymproject/sdk'; import { Grid } from '@mui/material'; +import { TestStatus } from './types'; import { Packets } from './Packets'; import { NodeScore } from './NodeScore'; import { Overview } from './Overview'; diff --git a/nym-wallet/src/components/TestNode/types.ts b/nym-wallet/src/components/TestNode/types.ts new file mode 100644 index 0000000000..0189f10b7b --- /dev/null +++ b/nym-wallet/src/components/TestNode/types.ts @@ -0,0 +1 @@ +export type TestStatus = 'Running' | 'Stopped' | 'Complete'; diff --git a/nym-wallet/src/pages/bonding/node-settings/node-test/index.tsx b/nym-wallet/src/pages/bonding/node-settings/node-test/index.tsx index 7670fe1dcd..ba9bf522f3 100644 --- a/nym-wallet/src/pages/bonding/node-settings/node-test/index.tsx +++ b/nym-wallet/src/pages/bonding/node-settings/node-test/index.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useContext, useEffect, useRef, useState } from 'react'; import { Box, Button } from '@mui/material'; import { Download } from '@mui/icons-material'; -import { NodeTestResultResponse, NodeTester, TestStatus, createNodeTesterClient } from '@nymproject/sdk'; +import { NodeTestResultResponse, NodeTester, createNodeTesterClient } from '@nymproject/node-tester'; import { format } from 'date-fns'; import { AppContext, useBondingContext } from 'src/context'; import { LoadingModal } from 'src/components/Modals/LoadingModal'; @@ -9,6 +9,7 @@ import { Results } from 'src/components/TestNode/Results'; import { ErrorModal } from 'src/components/Modals/ErrorModal'; import { PrintResults } from 'src/components/TestNode/PrintResults'; import { MAINNET_VALIDATOR_URL, QA_VALIDATOR_URL } from 'src/constants'; +import { TestStatus } from 'src/components/TestNode/types'; export const NodeTestPage = () => { const [nodeTestClient, setNodeTestClient] = useState(); diff --git a/package.json b/package.json index a967dafdee..1fbdb8bf82 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "private": true, "license": "Apache 2.0", "workspaces": [ + "dist/wasm/**", "sdk/typescript/packages/**", "ts-packages/*", "nym-wallet", @@ -13,8 +14,15 @@ "clients/validator" ], "scripts": { + "nuke": "npx rimraf **/node_modules node_modules", "clean": "lerna run clean", + + "build:ci:sdk": "run-s build:types build:packages build:wasm build:sdk:ci", + "build:sdk:ci": "lerna run --scope '{@nymproject/sdk,@nymproject/node-tester,@nymproject/sdk-react,@nymproject/mix-fetch}' build:dev --stream", + "build": "run-s build:types build:packages", + "build:wasm": "make sdk-wasm-build", + "build:sdk": "make sdk-typescript-build", "build:types": "lerna run --scope @nymproject/types build --stream", "build:packages": "run-s build:packages:theme build:packages:react", "build:packages:theme": "lerna run --scope @nymproject/mui-theme build", @@ -23,16 +31,21 @@ "build:playground": "lerna run --scope @nymproject/react storybook:build --stream", "build:ci": "yarn build && run-p build:react-example build:playground && yarn build:ci:collect-artifacts", "build:ci:collect-artifacts": "mkdir -p ts-packages/dist && mv ts-packages/react-components/storybook-static ts-packages/dist/storybook && mv ts-packages/react-webpack-with-theme-example/dist ts-packages/dist/example", + "docs:prod:build": "run-p docs:prod:build:ws docs:prod:build:ts:sdk", + "docs:prod:build:ws": "lerna run docs:prod:build --stream", + "docs:prod:build:ts:sdk": "cd sdk/typescript/docs && npm i && npm run docs:prod:build", + "sdk:build": "./sdk/typescript/scripts/build-prod-sdk.sh", + "sdk:publish": "./sdk/typescript/scripts/publish.sh", "lint": "lerna run lint --stream", "lint:fix": "lerna run lint:fix --stream", "tsc": "lerna run tsc --stream", "types:lint:fix": "lerna run lint:fix --scope @nymproject/types --scope @nymproject/nym-wallet-app", - "audit:fix": "npm_config_yes=true npx yarn-audit-fix -- --dry-run", - "preinstall": "yarn install:copy-placeholders", - "install:copy-placeholders": "cp scripts/build/yarn/wasm-placeholder/package.json sdk/typescript/packages/nym-client-wasm" + "audit:fix": "npm_config_yes=true npx yarn-audit-fix -- --dry-run" }, "devDependencies": { "lerna": "^6.6.2", - "npm-run-all": "^4.1.5" + "npm-run-all": "^4.1.5", + "@npmcli/node-gyp": "^3.0.0", + "node-gyp": "^9.3.1" } } \ No newline at end of file diff --git a/scripts/build/yarn/storage-placeholder/package.json b/scripts/build/yarn/storage-placeholder/package.json deleted file mode 100644 index 4a84a67b49..0000000000 --- a/scripts/build/yarn/storage-placeholder/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "@nymproject/extension-storage", - "version": "0.1.0", - "sideEffects": false -} diff --git a/scripts/build/yarn/wasm-placeholder/package.json b/scripts/build/yarn/wasm-placeholder/package.json deleted file mode 100644 index 50f57bc30d..0000000000 --- a/scripts/build/yarn/wasm-placeholder/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "@nymproject/nym-client-wasm", - "version": "1.0.0", - "sideEffects": false -} diff --git a/scripts/generate_changelog.sh b/scripts/generate_changelog.sh deleted file mode 100755 index 68b85e2ebd..0000000000 --- a/scripts/generate_changelog.sh +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2020 - The Nym Mixnet Authors -# SPDX-License-Identifier: Apache-2.0 - - -#!/bin/bash - -# Copyright 2020 Nym -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# set CHANGELOG_GITHUB_TOKEN in your .bashrc file -# For each version, you can add a release summary with text, images, gif animations, etc, and show new features and notes clearly to the user. This is done using GitHub metadata. - -# Example: adding the release summary for v1.0.0: - -# 1. Create a new GitHub Issue -# 2. In the Issue's Description field, add your release summary content -# 3. Set the Issue Label `release-summary` and add it to the GitHub Milestone `v1.0.0` -# 4. Close the Issue and execute `github-changelog-generator` -github_changelog_generator -u nymtech -p nym --exclude-tags 0.1.0,nym-wallet-v1.0.0-windows --token "$CHANGELOG_GITHUB_TOKEN" diff --git a/scripts/start_local_network.sh b/scripts/start_local_network.sh deleted file mode 100755 index 0bbbd4eaa3..0000000000 --- a/scripts/start_local_network.sh +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2020 - The Nym Mixnet Authors -# SPDX-License-Identifier: Apache-2.0 - -#!/bin/bash - -#// Copyright 2020 The Nym Mixnet Authors -#// -#// Licensed under the Apache License, Version 2.0 (the "License"); -#// you may not use this file except in compliance with the License. -#// You may obtain a copy of the License at -#// -#// http://www.apache.org/licenses/LICENSE-2.0 -#// -#// Unless required by applicable law or agreed to in writing, software -#// distributed under the License is distributed on an "AS IS" BASIS, -#// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -#// See the License for the specific language governing permissions and -#// limitations under the License. - -MAX_LAYERS=3 -NUMMIXES=3 - -function kill_old() { - echo "Killing old testnet processes..." - killall nym-mixnode - killall nym-gateway - killall nym-client -} - -if [ $# -ne 1 ]; then - echo "Expected a single argument to be passed - the directory server (that you should have independently started locally!)" - exit 1 -fi - -DIR=$1 - -echo "Press CTRL-C to stop." - -kill_old -export RUST_LOG=warning -# NOTE: If we wanted to suppress stdout and stderr, replace `&` with `> /dev/null 2>&1 &` in the `run` - -# cargo run --bin nym-gateway -- init --id gateway-local --mix-host 127.0.0.1:10000 --clients-host 127.0.0.1:10001 --directory $DIR -cargo run --release --bin nym-gateway -- run --id gateway-local & - -sleep 1 - -# Note: to disable logging (or direct it to another output) modify the constant on top of mixnode or provider; -# Will make it later either configurable by flags or config file. -for (( j=0; j<$NUMMIXES; j++ )); do - let layer=j%MAX_LAYERS+1 - cargo run --release --bin nym-mixnode -- init --id mix-local$j --host 127.0.0.1 --port $((9980+$j)) --layer $layer --directory $DIR - cargo run --release --bin nym-mixnode -- run --id mix-local$j & - sleep 1 -done - - -# just run forever (so we'd get all network warnings in this window and you wouldn't get confused when you started another process here) -# also it seems that SIGINT is nicely passed to all processes so they kill themselves -tail -f /dev/null diff --git a/sdk/rust/nym-sdk/Cargo.toml b/sdk/rust/nym-sdk/Cargo.toml index 6986e0ef15..9d8cdbe621 100644 --- a/sdk/rust/nym-sdk/Cargo.toml +++ b/sdk/rust/nym-sdk/Cargo.toml @@ -21,6 +21,13 @@ nym-task = { path = "../../../common/task" } nym-topology = { path = "../../../common/topology" } nym-socks5-client-core = { path = "../../../common/socks5-client-core" } nym-validator-client = { path = "../../../common/client-libs/validator-client", features = ["http-client"] } +nym-socks5-requests = { path = "../../../common/socks5/requests" } +nym-ordered-buffer = { path = "../../../common/socks5/ordered-buffer" } +nym-service-providers-common = { path = "../../../service-providers/common" } +bytecodec = "0.4.15" +httpcodec = "0.2.3" +bytes = "1" +http = "0.2.9" futures = { workspace = true } log = { workspace = true } diff --git a/sdk/rust/nym-sdk/examples/manually_overwrite_topology.rs b/sdk/rust/nym-sdk/examples/manually_overwrite_topology.rs index bad1c9651b..175a64f4cd 100644 --- a/sdk/rust/nym-sdk/examples/manually_overwrite_topology.rs +++ b/sdk/rust/nym-sdk/examples/manually_overwrite_topology.rs @@ -31,7 +31,7 @@ async fn main() { .parse() .unwrap(), layer: Layer::One, - version: "1.1.0".to_string(), + version: "1.1.0".into(), }], ); mixnodes.insert( @@ -48,7 +48,7 @@ async fn main() { .parse() .unwrap(), layer: Layer::Two, - version: "1.1.0".to_string(), + version: "1.1.0".into(), }], ); mixnodes.insert( @@ -65,7 +65,7 @@ async fn main() { .parse() .unwrap(), layer: Layer::Three, - version: "1.1.0".to_string(), + version: "1.1.0".into(), }], ); diff --git a/sdk/rust/nym-sdk/examples/mixfetch.rs b/sdk/rust/nym-sdk/examples/mixfetch.rs new file mode 100644 index 0000000000..c71503e9f1 --- /dev/null +++ b/sdk/rust/nym-sdk/examples/mixfetch.rs @@ -0,0 +1,166 @@ +extern crate core; + +// use bytecodec::bytes::BytesEncoder; +// use bytecodec::bytes::RemainingBytesDecoder; +// use bytecodec::io::IoEncodeExt; +// use bytecodec::{DecodeExt, Encode}; +// use httpcodec::{BodyDecoder, ResponseDecoder}; +// use httpcodec::{ +// BodyEncoder, HeaderField, HttpVersion, Method, Request, RequestEncoder, RequestTarget, +// }; +// use nym_sdk::mixnet; +// use nym_sdk::mixnet::{IncludedSurbs, Recipient}; +// use nym_service_providers_common::interface::Serializable; +// use nym_socks5_requests::{ +// Socks5ProtocolVersion, Socks5ProviderRequest, Socks5Response, Socks5ResponseContent, +// }; +// use std::time::Duration; + +#[tokio::main] +async fn main() { + unimplemented!() + // nym_bin_common::logging::setup_logging(); + // + // // Passing no config makes the client fire up an ephemeral session and figure shit out on its own + // let mut client = mixnet::MixnetClient::connect_new().await.unwrap(); + // + // // Be able to get our client address + // let our_address = client.nym_address(); + // println!("Our client nym address is: {our_address}"); + // + // // Send a message through the mixnet to ourselves + // // client.send_str(*our_address, "hello there").await; + // + // // Build an HTTP GET request + // let mut request = Request::new( + // Method::new("GET").unwrap(), + // RequestTarget::new("/.wellknown/wallet/validators.json").unwrap(), + // HttpVersion::V1_1, + // b"", + // ); + // let mut headers = request.header_mut(); + // headers.add_field(HeaderField::new("Host", "nymtech.net").unwrap()); + // + // // Set up an HTTP GET request, with headers and no payload + // // let mut request = Request::new( + // // Method::new("GET").unwrap(), + // // RequestTarget::new("/package.json").unwrap(), + // // HttpVersion::V1_1, + // // b"", + // // ); + // // let mut headers = request.header_mut(); + // // headers.add_field(HeaderField::new("Host", "localhost:3000").unwrap()); + // + // // Encode as bytes + // let mut encoder = RequestEncoder::new(BodyEncoder::new(BytesEncoder::new())); + // encoder.start_encoding(request).unwrap(); + // let mut buf = Vec::new(); + // encoder.encode_all(&mut buf).unwrap(); + // + // println!("{:?}", buf); + // println!("{}", String::from_utf8_lossy(&buf)); + // + // let client_address = Recipient::try_from_base58_string("8YF6f8x17j3fviBdU87EGD9g9MAgn9DARxunwLEVM7Bm.4ydfpjbTjCmzj58hWdQjxU2gT6CRVnTbnKajr2hAGBBM@2xU4CBE6QiiYt6EyBXSALwxkNvM7gqJfjHXaMkjiFmYW") + // .expect("address is valid"); + // + // // Any old connection id will do + // let conn_id = 13488440783042593894u64; + // + // // Wrap is SOCKS5 connect request + // let socks5_connect = nym_socks5_requests::request::Socks5Request::new_connect( + // Socks5ProtocolVersion::Legacy, + // conn_id, + // "nymtech.net:443".to_string(), + // // "localhost:3000".to_string(), + // Some(*our_address), + // ); + // nym_socks5_requests::request::Socks5Request::try_from_bytes( + // &socks5_connect.clone().into_bytes(), + // ) + // .unwrap(); + // + // let msg_connect = Socks5ProviderRequest::new_provider_data( + // nym_socks5_client_core::config::Config::default() + // .get_socks5() + // .get_provider_interface_version(), + // socks5_connect, + // ); + // + // client + // .send_bytes( + // client_address, + // msg_connect.into_bytes(), + // IncludedSurbs::ExposeSelfAddress, + // ) + // .await; + // + // // Sleep to avoid weird packet ordering + // tokio::time::sleep(Duration::from_millis(1000u64)).await; + // + // // Create an ordered message + // let ordered_msg = OrderedMessage { + // data: buf, + // index: 0, + // }; + // + // let buf2 = ordered_msg.into_bytes(); + // println!("socks5 with payload: {:?}", &buf2); + // + // // Wrap is SOCKS5 send request + // let socks5_send = nym_socks5_requests::request::Socks5Request::new_send( + // Socks5ProtocolVersion::Legacy, + // conn_id, + // buf2, + // false, + // ); + // + // let msg_send = Socks5ProviderRequest::new_provider_data( + // nym_socks5_client_core::config::Config::default() + // .get_socks5() + // .get_provider_interface_version(), + // socks5_send, + // ); + // + // client + // .send_bytes( + // client_address, + // msg_send.into_bytes(), + // IncludedSurbs::ExposeSelfAddress, + // ) + // .await; + // + // println!("Waiting for message (ctrl-c to exit)"); + // client + // .on_messages(|msg| { + // if let Ok(res) = Socks5Response::try_from_bytes(msg.message.as_slice()) { + // println!("️✅ Socks5Response: {:?}", res); + // if let Socks5ResponseContent::NetworkData(data) = res.content { + // // data.data is really an OrderedMessage + // let response_ordered_message = + // OrderedMessage::try_from_bytes(data.data).unwrap(); + // + // println!( + // "️🤖 Socks5ResponseContent::NetworkData: {}", + // String::from_utf8_lossy(&response_ordered_message.data) + // ); + // + // if !response_ordered_message.data.is_empty() { + // println!("️✅ resp: {:?}", response_ordered_message.data); + // + // // let response = http::response::Response::try_parse(resp).unwrap(); + // let mut decoder = + // ResponseDecoder::>::default(); + // let response = decoder + // .decode_from_bytes(response_ordered_message.data.as_ref()) + // .unwrap(); + // + // println!("➡️ decoded: {:?}", response); + // println!("🚀 decoded: {}", String::from_utf8_lossy(response.body())); + // } + // } + // } + // + // // println!("️✅ Received: {}", String::from_utf8_lossy(&msg.message)) + // }) + // .await; +} diff --git a/sdk/typescript/.eslintrc.js b/sdk/typescript/.eslintrc.js index 52bd4fe9a9..14620fcb06 100644 --- a/sdk/typescript/.eslintrc.js +++ b/sdk/typescript/.eslintrc.js @@ -109,7 +109,7 @@ module.exports = { 'root-import': { rootPathPrefix: '@', rootPathSuffix: 'src', - extensions: ['.js', '.ts', '.tsx', '.jsx', '.mdx'], + extensions: ['.js', '.ts', '.tsx', '.jsx', '.mdx', '.mjs'], }, }, }, diff --git a/sdk/typescript/codegen/.gitignore b/sdk/typescript/codegen/.gitignore new file mode 100644 index 0000000000..53253fe4cb --- /dev/null +++ b/sdk/typescript/codegen/.gitignore @@ -0,0 +1,2 @@ +docs +dist \ No newline at end of file diff --git a/ts-packages/react-components/.eslintrc.json b/sdk/typescript/codegen/contract-clients/.eslintrc.json similarity index 100% rename from ts-packages/react-components/.eslintrc.json rename to sdk/typescript/codegen/contract-clients/.eslintrc.json diff --git a/sdk/typescript/codegen/contract-clients/README.md b/sdk/typescript/codegen/contract-clients/README.md new file mode 100644 index 0000000000..c311b7e9c7 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/README.md @@ -0,0 +1,34 @@ +# Nym Smart Contract Clients + +This package contains read-only query and signing clients for all Nym's smart contracts. + +## Usage + +First install the package and its dependencies from Cosmos Stargate: + +``` +npm install @nymproject/contract-clients @cosmjs/cosmwasm-stargate @cosmjs/proto-signing +``` + +Then execute some methods, signing them with a mnemonic: + +```ts +import { contracts } from '@nymproject/contract-clients'; +import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; +import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; + +async function main() { + // generate a signer from a mnemonic + const signer = await DirectSecp256k1HdWallet.fromMnemonic("..."); + const accounts = await signer.getAccounts(); + + // make a signing client for the Nym Mixnet contract on mainnet + const cosmWasmSigningClient = await SigningCosmWasmClient.connectWithSigner("rpc.nymtech.net:443", signer); + const client = new contracts.Mixnet.MixnetClient(cosmWasmSigningClient, accounts[0].address, 'n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr'); + + // delegate 1 NYM to mixnode with id 100 + const result = await client.delegateToMixnode({ mixId: 100 }, 'auto', undefined, [{ amount: `${1_000_000}`, denom: 'unym' }]); + + console.log(`Tx Hash = ${result.transactionHash}`); +} +``` diff --git a/sdk/typescript/codegen/contract-clients/build.mjs b/sdk/typescript/codegen/contract-clients/build.mjs new file mode 100644 index 0000000000..5a6b6220f6 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/build.mjs @@ -0,0 +1,36 @@ +import codegen from '@cosmwasm/ts-codegen'; + +codegen + .default({ + contracts: [ + { name: 'coconut-bandwidth', dir: '../../../../contracts/coconut-bandwidth' }, + { name: 'coconut-dkg', dir: '../../../../contracts/coconut-dkg' }, + { name: 'mixnet', dir: '../../../../contracts/mixnet' }, + { name: 'cw3-flex-multisig', dir: '../../../../contracts/multisig/cw3-flex-multisig' }, + { name: 'cw4-group', dir: '../../../../contracts/multisig/cw4-group' }, + { name: 'name-service', dir: '../../../../contracts/name-service' }, + { name: 'service-provider-directory', dir: '../../../../contracts/service-provider-directory' }, + { name: 'vesting', dir: '../../../../contracts/vesting' }, + ], + outPath: './src', + + // options are completely optional ;) + options: { + bundle: { + bundleFile: 'index.ts', + scope: 'contracts', + }, + types: { + enabled: true, + }, + client: { + enabled: true, + }, + // useContractsHooks: { + // enabled: false, + // }, + }, + }) + .then(() => { + console.log('✨ all done!'); + }); diff --git a/sdk/typescript/codegen/contract-clients/internal-dev/index.ts b/sdk/typescript/codegen/contract-clients/internal-dev/index.ts new file mode 100644 index 0000000000..ec5a003726 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/internal-dev/index.ts @@ -0,0 +1,18 @@ +import { contracts } from '@nymproject/contract-clients'; +import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; +import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; + +async function main() { + // generate a signer from a mnemonic + const signer = await DirectSecp256k1HdWallet.fromMnemonic("..."); + const accounts = await signer.getAccounts(); + + // make a signing client for the Nym Mixnet contract on mainnet + const cosmWasmSigningClient = await SigningCosmWasmClient.connectWithSigner("https://rpc.nymtech.net:443", signer); + const client = new contracts.Mixnet.MixnetClient(cosmWasmSigningClient, accounts[0].address, 'n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr'); + + // delegate 1 NYM to mixnode with id 100 + const result = await client.delegateToMixnode({ mixId: 100 }, 'auto', undefined, [{ amount: `${1_000_000}`, denom: 'unym' }]); + + console.log(`Tx Hash = ${result.transactionHash}`); +} diff --git a/sdk/typescript/codegen/contract-clients/internal-dev/package-lock.json b/sdk/typescript/codegen/contract-clients/internal-dev/package-lock.json new file mode 100644 index 0000000000..04498662ff --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/internal-dev/package-lock.json @@ -0,0 +1,28 @@ +{ + "name": "internal-dev-contract-clients", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "internal-dev-contract-clients", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@nymproject/contract-clients": "file:.." + } + }, + "..": { + "version": "1.0.0", + "license": "Apache-2.0", + "devDependencies": { + "@cosmwasm/ts-codegen": "^0.35.3", + "typescript": "^4.6.2" + } + }, + "node_modules/@nymproject/contract-clients": { + "resolved": "..", + "link": true + } + } +} diff --git a/sdk/typescript/codegen/contract-clients/internal-dev/package.json b/sdk/typescript/codegen/contract-clients/internal-dev/package.json new file mode 100644 index 0000000000..e41a628208 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/internal-dev/package.json @@ -0,0 +1,14 @@ +{ + "name": "internal-dev-contract-clients", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "dependencies": { + "@nymproject/contract-clients": "file:.." + }, + "author": "", + "license": "ISC" +} diff --git a/sdk/typescript/codegen/contract-clients/package-lock.json b/sdk/typescript/codegen/contract-clients/package-lock.json new file mode 100644 index 0000000000..219b1f89f7 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/package-lock.json @@ -0,0 +1,6508 @@ +{ + "name": "@nymproject/contract-clients", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@nymproject/contract-clients", + "version": "1.0.0", + "license": "Apache-2.0", + "devDependencies": { + "@cosmwasm/ts-codegen": "^0.35.3", + "nodemon": "3.0.1", + "npm-run-all": "^4.1.5", + "reload": "^3.2.1", + "typedoc": "^0.24.8", + "typescript": "^4.6.2" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", + "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.22.10", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", + "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz", + "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.10", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helpers": "^7.18.9", + "@babel/parser": "^7.18.10", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.10", + "@babel/types": "^7.18.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.18.12", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz", + "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.10", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure/node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.10.tgz", + "integrity": "sha512-Av0qubwDQxC56DoUReVDeLfMEjYYSN1nZrTUrWkXd7hpU73ymRANkbuDm3yni9npkn+RXy9nNbEJZEzXr7xrfQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor/node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", + "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.5", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.10.tgz", + "integrity": "sha512-5IBb77txKYQPpOEdUdIhBx8VrZyDCQ+H82H0+5dX1TmuscP5vJKEE3cKurjtIw/vFwzbVH48VweE78kVDBrqjA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz", + "integrity": "sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", + "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", + "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", + "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name/node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables/node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz", + "integrity": "sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions/node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports/node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", + "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression/node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz", + "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-wrap-function": "^7.22.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz", + "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access/node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers/node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration/node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz", + "integrity": "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function/node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz", + "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.10", + "@babel/types": "^7.22.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers/node_modules/@babel/generator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", + "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.10", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers/node_modules/@babel/parser": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", + "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helpers/node_modules/@babel/traverse": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz", + "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.10", + "@babel/types": "^7.22.10", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers/node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", + "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.5", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz", + "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz", + "integrity": "sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz", + "integrity": "sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", + "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", + "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-default-from": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.18.10.tgz", + "integrity": "sha512-5H2N3R2aQFxkV4PIBUR/i7PUSwgTZjouJKzI8eKswfIjT0PhvzkPn0t0wIS5zn6maQuvtT0t1oHtMUz61LOuow==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-default-from": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", + "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", + "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz", + "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.18.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-default-from": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.22.5.tgz", + "integrity": "sha512-ODAqWWXB/yReh/jVQDag/3/tl6lgBueQkk/TcfW/59Oykm4c8a55XloX0CTk2k2VJiFWMgHby9xNX29IbCv9dQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", + "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", + "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", + "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz", + "integrity": "sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz", + "integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", + "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz", + "integrity": "sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", + "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", + "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", + "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz", + "integrity": "sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", + "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", + "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", + "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz", + "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz", + "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz", + "integrity": "sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", + "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", + "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", + "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.10.tgz", + "integrity": "sha512-MMkQqZAZ+MGj+jGTG3OTuhKeBpNcO+0oCEbrGNEaOmiEn+1MzRyQlYsruGiU8RTK3zV6XwrVJTmwiDOyYK6J9g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz", + "integrity": "sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", + "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", + "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", + "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.10.tgz", + "integrity": "sha512-q5mMeYAdfEbpBAgzl7tBre/la3LeCxmDO1+wMXRdPWbcoMjR3GiXlCLk7JBZVVye0bqTGNMbt0yYVXX1B1jEWQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "babel-plugin-polyfill-corejs2": "^0.3.2", + "babel-plugin-polyfill-corejs3": "^0.5.3", + "babel-plugin-polyfill-regenerator": "^0.4.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", + "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", + "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", + "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", + "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", + "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.10.tgz", + "integrity": "sha512-7++c8I/ymsDo4QQBAgbraXLzIM6jmfao11KgIBEYZRReWzNWH9NtNgJcyrZiXsOPh523FQm6LfpLyy/U5fn46A==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.10", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-typescript": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", + "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", + "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.10.tgz", + "integrity": "sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-async-generator-functions": "^7.18.10", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.18.9", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.18.6", + "@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/plugin-transform-arrow-functions": "^7.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.18.9", + "@babel/plugin-transform-classes": "^7.18.9", + "@babel/plugin-transform-computed-properties": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.18.9", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.9", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-function-name": "^7.18.9", + "@babel/plugin-transform-literals": "^7.18.9", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.18.6", + "@babel/plugin-transform-modules-commonjs": "^7.18.6", + "@babel/plugin-transform-modules-systemjs": "^7.18.9", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.18.8", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.18.9", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.9", + "@babel/plugin-transform-typeof-symbol": "^7.18.9", + "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-regex": "^7.18.6", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.18.10", + "babel-plugin-polyfill-corejs2": "^0.3.2", + "babel-plugin-polyfill-corejs3": "^0.5.3", + "babel-plugin-polyfill-regenerator": "^0.4.0", + "core-js-compat": "^3.22.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz", + "integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.22.5.tgz", + "integrity": "sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.22.5", + "@babel/plugin-transform-typescript": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "node_modules/@babel/runtime": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz", + "integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template/node_modules/@babel/parser": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", + "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template/node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz", + "integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.10", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.11", + "@babel/types": "^7.18.10", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz", + "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cosmwasm/ts-codegen": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@cosmwasm/ts-codegen/-/ts-codegen-0.35.3.tgz", + "integrity": "sha512-L7T4yjAQIWJ/h0YmqVjihzv78ZbqGD/f0G8EJTwccsPXqWzbcnXzQKsvtFXpDp6AzaJKVMchFHfp6ZPRP3boUQ==", + "dev": true, + "dependencies": { + "@babel/core": "7.18.10", + "@babel/generator": "7.18.12", + "@babel/parser": "7.18.11", + "@babel/plugin-proposal-class-properties": "7.18.6", + "@babel/plugin-proposal-export-default-from": "7.18.10", + "@babel/plugin-proposal-object-rest-spread": "7.18.9", + "@babel/plugin-transform-runtime": "7.18.10", + "@babel/preset-env": "7.18.10", + "@babel/preset-typescript": "^7.18.6", + "@babel/runtime": "^7.18.9", + "@babel/traverse": "7.18.11", + "@babel/types": "7.18.10", + "@pyramation/json-schema-to-typescript": " 11.0.4", + "case": "1.6.3", + "dargs": "7.0.0", + "deepmerge": "4.2.2", + "dotty": "0.1.2", + "fuzzy": "0.1.3", + "glob": "8.0.3", + "inquirerer": "0.1.3", + "long": "^5.2.0", + "minimist": "1.2.6", + "mkdirp": "1.0.4", + "parse-package-name": "1.0.0", + "rimraf": "3.0.2", + "shelljs": "0.8.5", + "wasm-ast-types": "^0.26.2" + }, + "bin": { + "cosmwasm-ts-codegen": "main/ts-codegen.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.3.tgz", + "integrity": "sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^28.1.3", + "@jridgewell/trace-mapping": "^0.3.13", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.3", + "jest-regex-util": "^28.0.2", + "jest-util": "^28.1.3", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.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" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "dev": true + }, + "node_modules/@pyramation/json-schema-ref-parser": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@pyramation/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz", + "integrity": "sha512-L5kToHAEc1Q87R8ZwWFaNa4tPHr8Hnm+U+DRdUVq3tUtk+EX4pCqSd34Z6EMxNi/bjTzt1syAG9J2Oo1YFlqSg==", + "dev": true, + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "js-yaml": "^3.13.1" + } + }, + "node_modules/@pyramation/json-schema-to-typescript": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@pyramation/json-schema-to-typescript/-/json-schema-to-typescript-11.0.4.tgz", + "integrity": "sha512-+aSzXDLhMHOEdV2cJ7Tjg/9YenjHU5BCmClVygzwxJZ1R16NOfEn7lTAwVzb/2jivOSnhjHzMJbnSf8b6rd1zg==", + "dev": true, + "dependencies": { + "@pyramation/json-schema-ref-parser": "9.0.6", + "@types/json-schema": "^7.0.11", + "@types/lodash": "^4.14.182", + "@types/prettier": "^2.6.1", + "cli-color": "^2.0.2", + "get-stdin": "^8.0.0", + "glob": "^7.1.6", + "glob-promise": "^4.2.2", + "is-glob": "^4.0.3", + "lodash": "^4.17.21", + "minimist": "^1.2.6", + "mkdirp": "^1.0.4", + "mz": "^2.7.0", + "prettier": "^2.6.2" + }, + "bin": { + "json2ts": "dist/src/cli.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@pyramation/json-schema-to-typescript/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@pyramation/json-schema-to-typescript/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@pyramation/json-schema-to-typescript/node_modules/glob-promise": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-4.2.2.tgz", + "integrity": "sha512-xcUzJ8NWN5bktoTIX7eOclO1Npxd/dyVqUJxlLIDasT4C7KZyqlPIwkdJ0Ypiy3p2ZKahTjK4M9uC3sNSfNMzw==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/ahmadnassri" + }, + "peerDependencies": { + "glob": "^7.1.6" + } + }, + "node_modules/@pyramation/json-schema-to-typescript/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "dev": true + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.14.197", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", + "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.3.tgz", + "integrity": "sha512-ITI7rbWczR8a/S6qjAW7DMqxqFMjjTo61qZVWJ1ubPvbIQsL5D/TvwjYEalM8Kthpe3hTzOGrF2TGbAu2uyqeA==", + "dev": true + }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-stringify": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ast-stringify/-/ast-stringify-0.1.0.tgz", + "integrity": "sha512-J1PgFYV3RG6r37+M6ySZJH406hR82okwGvFM9hLXpOvdx4WC4GEW8/qiw6pi1hKTrqcRvoHP8a7mp87egYr6iA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.11.2" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", + "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.17.7", + "@babel/helper-define-polyfill-provider": "^0.3.3", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz", + "integrity": "sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.2", + "core-js-compat": "^3.21.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", + "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.11" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001522", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001522.tgz", + "integrity": "sha512-TKiyTVZxJGhsTszLuzb+6vUZSjVOAhClszBr2Ta2k9IwtNBT/4dzmL6aywt0HCgEZlmwJzXJd8yNiob6HgwTRg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/case": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz", + "integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-color": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.3.tgz", + "integrity": "sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.61", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.15", + "timers-ext": "^0.1.7" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "dev": true, + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/commander": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", + "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/core-js-compat": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.1.tgz", + "integrity": "sha512-GSvKDv4wE0bPnQtjklV101juQ85g6H3rm5PDP20mqlS5j0kXF3pP97YvAu5hl+uFHqMictp3b2VxOHljWMAtuA==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/cross-spawn/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dotty": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dotty/-/dotty-0.1.2.tgz", + "integrity": "sha512-V0EWmKeH3DEhMwAZ+8ZB2Ao4OK6p++Z0hsDtZq3N0+0ZMVqkzrcEGROvOnZpLnvBg5PTNG23JEDLAm64gPaotQ==", + "dev": true + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.499", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.499.tgz", + "integrity": "sha512-0NmjlYBLKVHva4GABWAaHuPJolnDuL0AhV3h1hES6rcLCWEIbRL6/8TghfsVwkx6TEroQVdliX7+aLysUpKvjw==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.1", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.1", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dev": true, + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", + "dev": true + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fuzzy": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/fuzzy/-/fuzzy-0.1.3.tgz", + "integrity": "sha512-/gZffu4ykarLrCiP3Ygsa86UAo1E5vEVlvTrpkKywXSbP9Xhln3oSp9QSV57gEq3JFFpGJ4GZ+5zdEp3FcUh4w==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/inquirer-autocomplete-prompt": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-0.11.1.tgz", + "integrity": "sha512-VM4eNiyRD4CeUc2cyKni+F8qgHwL9WC4LdOr+mEC85qP/QNsDV+ysVqUrJYhw1TmDQu1QVhc8hbaL7wfk8SJxw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^2.0.0", + "chalk": "^1.1.3", + "figures": "^2.0.0", + "inquirer": "3.1.1", + "lodash": "^4.17.4", + "run-async": "^2.3.0", + "util": "^0.10.3" + } + }, + "node_modules/inquirer-autocomplete-prompt/node_modules/ansi-escapes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz", + "integrity": "sha512-tH/fSoQp4DrEodDK3QpdiWiZTSe7sBJ9eOqcQBZ0o9HTM+5M/viSEn+sPMoTuPjQQ8n++w3QJoPEjt8LVPcrCg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/inquirer-autocomplete-prompt/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer-autocomplete-prompt/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer-autocomplete-prompt/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer-autocomplete-prompt/node_modules/chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha512-j/Toj7f1z98Hh2cYo2BVr85EpIRWqUi7rtRSGxh/cqUjqrnJe9l9UE7IUGd2vQ2p+kSHLkSzObQPZPLUC6TQwg==", + "dev": true + }, + "node_modules/inquirer-autocomplete-prompt/node_modules/external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "dependencies": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/inquirer-autocomplete-prompt/node_modules/inquirer": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.1.1.tgz", + "integrity": "sha512-H50sHQwgvvaTBd3HpKMVtL/u6LoHDvYym51gd7bGQe/+9HkCE+J0/3N5FJLfd6O6oz44hHewC2Pc2LodzWVafQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.0.0", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } + }, + "node_modules/inquirer-autocomplete-prompt/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inquirer-autocomplete-prompt/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/inquirerer": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/inquirerer/-/inquirerer-0.1.3.tgz", + "integrity": "sha512-yGgLUOqPxTsINBjZNZeLi3cv2zgxXtw9feaAOSJf2j6AqIT5Uxs5ZOqOrfAf+xP65Sicla1FD3iDxa3D6TsCAQ==", + "dev": true, + "dependencies": { + "colors": "^1.1.2", + "inquirer": "^6.0.0", + "inquirer-autocomplete-prompt": "^0.11.1" + } + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-haste-map": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.3.tgz", + "integrity": "sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.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": "^28.0.2", + "jest-util": "^28.1.3", + "jest-worker": "^28.1.3", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", + "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "dev": true, + "dependencies": { + "es5-ext": "~0.10.2" + } + }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==", + "dev": true + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, + "node_modules/nodemon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.1.tgz", + "integrity": "sha512-g9AZ7HmkhQkqXkRc20w+ZfQ73cHLbE8hnPbtaFbFtCumZsjyMhKk9LajQ07U5Ux28lvFjZ5X7HvWR1xzU8jHVw==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemon/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemon/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm-run-all/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/npm-run-all/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parse-package-name": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-package-name/-/parse-package-name-1.0.0.tgz", + "integrity": "sha512-kBeTUtcj+SkyfaW4+KBe0HtsloBJ/mKTPoxpVdA57GZiPerREsUWJOhVj9anXweFiJkm5y8FG1sxFZkZ0SN6wg==", + "dev": true + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", + "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/reload": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/reload/-/reload-3.2.1.tgz", + "integrity": "sha512-ZdM8ZSEeI72zkhh6heMEvJ0vHZoovZXcJI6Zae8CzS7o5vO/WjZsAMMr0y1+3I/fCN7y7ZxABoUwwCswcLHkjQ==", + "dev": true, + "dependencies": { + "cli-color": "~2.0.0", + "commander": "~9.4.0", + "finalhandler": "~1.2.0", + "minimist": "~1.2.0", + "open": "^8.0.0", + "serve-static": "~1.15.0", + "supervisor": "~0.12.0", + "ws": "~8.11.0" + }, + "bin": { + "reload": "bin/reload" + } + }, + "node_modules/resolve": { + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "dev": true, + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha512-Cun9QucwK6MIrp3mry/Y7hqD1oFqTYLQ4pGxaHTjIdaFDWRGGLikqp6u8LcWJnzpoALg9hap+JGk8sFIUuEGNA==", + "dev": true + }, + "node_modules/rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha512-3xPNZGW93oCjiO7PtKxRK6iOVYBWBvtf9QHDfU23Oc+dLIQmAV//UnyXV/yihv81VS/UqoQPk4NegS8EFi55Hg==", + "dev": true, + "dependencies": { + "rx-lite": "*" + } + }, + "node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dev": true, + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/shelljs/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/shelljs/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/shelljs/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/shiki": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.3.tgz", + "integrity": "sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==", + "dev": true, + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string.prototype.padend": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz", + "integrity": "sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/supervisor": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/supervisor/-/supervisor-0.12.0.tgz", + "integrity": "sha512-iBYeU5Or4WiiIa3+ns1DpHIiHjNNXSuYUiixKcznewwo4ImBJ8EobktaAo2csOcauhrz4SvKRTou8Z2C3W28+A==", + "dev": true, + "bin": { + "node-supervisor": "lib/cli-wrapper.js", + "supervisor": "lib/cli-wrapper.js" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "dependencies": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedoc": { + "version": "0.24.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", + "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", + "dev": true, + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.0", + "shiki": "^0.14.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 14.14" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/wasm-ast-types": { + "version": "0.26.2", + "resolved": "https://registry.npmjs.org/wasm-ast-types/-/wasm-ast-types-0.26.2.tgz", + "integrity": "sha512-DM34W0Sexd/BreN4g1ZjfaDC8hkKIw3FykV7vT9KdhCoroH+Qncz+jvSEI0fEDqbtJkWiP9Z+u61a5LPObHKaA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.18.9", + "@babel/types": "7.18.10", + "@jest/transform": "28.1.3", + "ast-stringify": "0.1.0", + "case": "1.6.3", + "deepmerge": "4.2.2" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } +} diff --git a/sdk/typescript/codegen/contract-clients/package.json b/sdk/typescript/codegen/contract-clients/package.json new file mode 100644 index 0000000000..7f70204918 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/package.json @@ -0,0 +1,29 @@ +{ + "name": "@nymproject/contract-clients", + "version": "1.2.0-rc.1", + "description": "A client for all Nym smart contracts", + "main": "dist/index.js", + "browser": "dist/index.js", + "types": "./dist/index.d.ts", + "scripts": { + "build": "tsc", + "build:autogen": "node build.mjs", + "docs:dev": "run-p docs:watch docs:serve ", + "docs:generate": "typedoc", + "docs:generate:prod": "typedoc --basePath ./docs/tsdoc/nymproject/contract-clients/", + "docs:prod:build": "scripts/build-prod-docs-collect.sh", + "docs:serve": "reload -b -d ./docs -p 3000", + "docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\"" + }, + "devDependencies": { + "@cosmwasm/ts-codegen": "^0.35.3", + "nodemon": "3.0.1", + "npm-run-all": "^4.1.5", + "reload": "^3.2.1", + "typescript": "^4.6.2", + "typedoc": "^0.24.8" + }, + "keywords": [], + "author": "", + "license": "Apache-2.0" +} diff --git a/sdk/typescript/codegen/contract-clients/src/CoconutBandwidth.client.ts b/sdk/typescript/codegen/contract-clients/src/CoconutBandwidth.client.ts new file mode 100644 index 0000000000..a28f6af9b4 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/CoconutBandwidth.client.ts @@ -0,0 +1,130 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; +import { StdFee } from "@cosmjs/amino"; +import { InstantiateMsg, ExecuteMsg, Uint128, DepositData, SpendCredentialData, Coin, QueryMsg, MigrateMsg, Addr, SpendCredentialStatus, PagedSpendCredentialResponse, SpendCredential, SpendCredentialResponse } from "./CoconutBandwidth.types"; + +export interface CoconutBandwidthReadOnlyInterface { + contractAddress: string; + getSpentCredential: ({ + blindedSerialNumber + }: { + blindedSerialNumber: string; + }) => Promise; + getAllSpentCredentials: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }) => Promise; +} +export class CoconutBandwidthQueryClient implements CoconutBandwidthReadOnlyInterface { + client: CosmWasmClient; + contractAddress: string; + + constructor(client: CosmWasmClient, contractAddress: string) { + this.client = client; + this.contractAddress = contractAddress; + this.getSpentCredential = this.getSpentCredential.bind(this); + this.getAllSpentCredentials = this.getAllSpentCredentials.bind(this); + } + + getSpentCredential = async ({ + blindedSerialNumber + }: { + blindedSerialNumber: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_spent_credential: { + blinded_serial_number: blindedSerialNumber + } + }); + }; + getAllSpentCredentials = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_all_spent_credentials: { + limit, + start_after: startAfter + } + }); + }; +} +export interface CoconutBandwidthInterface extends CoconutBandwidthReadOnlyInterface { + contractAddress: string; + sender: string; + depositFunds: ({ + data + }: { + data: DepositData; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + spendCredential: ({ + data + }: { + data: SpendCredentialData; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + releaseFunds: ({ + funds + }: { + funds: Coin; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; +} +export class CoconutBandwidthClient extends CoconutBandwidthQueryClient implements CoconutBandwidthInterface { + client: SigningCosmWasmClient; + sender: string; + contractAddress: string; + + constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) { + super(client, contractAddress); + this.client = client; + this.sender = sender; + this.contractAddress = contractAddress; + this.depositFunds = this.depositFunds.bind(this); + this.spendCredential = this.spendCredential.bind(this); + this.releaseFunds = this.releaseFunds.bind(this); + } + + depositFunds = async ({ + data + }: { + data: DepositData; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + deposit_funds: { + data + } + }, fee, memo, _funds); + }; + spendCredential = async ({ + data + }: { + data: SpendCredentialData; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + spend_credential: { + data + } + }, fee, memo, _funds); + }; + releaseFunds = async ({ + funds + }: { + funds: Coin; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + release_funds: { + funds + } + }, fee, memo, _funds); + }; +} diff --git a/sdk/typescript/codegen/contract-clients/src/CoconutBandwidth.types.ts b/sdk/typescript/codegen/contract-clients/src/CoconutBandwidth.types.ts new file mode 100644 index 0000000000..f6ef153300 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/CoconutBandwidth.types.ts @@ -0,0 +1,67 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +export interface InstantiateMsg { + mix_denom: string; + multisig_addr: string; + pool_addr: string; +} +export type ExecuteMsg = { + deposit_funds: { + data: DepositData; + }; +} | { + spend_credential: { + data: SpendCredentialData; + }; +} | { + release_funds: { + funds: Coin; + }; +}; +export type Uint128 = string; +export interface DepositData { + deposit_info: string; + encryption_key: string; + identity_key: string; +} +export interface SpendCredentialData { + blinded_serial_number: string; + funds: Coin; + gateway_cosmos_address: string; +} +export interface Coin { + amount: Uint128; + denom: string; + [k: string]: unknown; +} +export type QueryMsg = { + get_spent_credential: { + blinded_serial_number: string; + }; +} | { + get_all_spent_credentials: { + limit?: number | null; + start_after?: string | null; + }; +}; +export interface MigrateMsg {} +export type Addr = string; +export type SpendCredentialStatus = "in_progress" | "spent"; +export interface PagedSpendCredentialResponse { + per_page: number; + spend_credentials: SpendCredential[]; + start_next_after?: string | null; +} +export interface SpendCredential { + blinded_serial_number: string; + funds: Coin; + gateway_cosmos_address: Addr; + status: SpendCredentialStatus; +} +export interface SpendCredentialResponse { + spend_credential?: SpendCredential | null; +} \ No newline at end of file diff --git a/sdk/typescript/codegen/contract-clients/src/CoconutDkg.client.ts b/sdk/typescript/codegen/contract-clients/src/CoconutDkg.client.ts new file mode 100644 index 0000000000..c86b48d22c --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/CoconutDkg.client.ts @@ -0,0 +1,283 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; +import { Coin, StdFee } from "@cosmjs/amino"; +import { InstantiateMsg, TimeConfiguration, ExecuteMsg, ContractSafeBytes, Addr, QueryMsg, MigrateMsg, PagedDealerResponse, DealerDetails, Timestamp, Uint64, EpochState, Epoch, DealerType, DealerDetailsResponse, PagedDealingsResponse, ContractDealing, NullableInitialReplacementData, InitialReplacementData, PagedVKSharesResponse, ContractVKShare } from "./CoconutDkg.types"; + +export interface CoconutDkgReadOnlyInterface { + contractAddress: string; + getCurrentEpochState: () => Promise; + getCurrentEpochThreshold: () => Promise; + getInitialDealers: () => Promise; + getDealerDetails: ({ + dealerAddress + }: { + dealerAddress: string; + }) => Promise; + getCurrentDealers: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }) => Promise; + getPastDealers: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }) => Promise; + getDealing: ({ + idx, + limit, + startAfter + }: { + idx: number; + limit?: number; + startAfter?: string; + }) => Promise; + getVerificationKeys: ({ + epochId, + limit, + startAfter + }: { + epochId: number; + limit?: number; + startAfter?: string; + }) => Promise; +} +export class CoconutDkgQueryClient implements CoconutDkgReadOnlyInterface { + client: CosmWasmClient; + contractAddress: string; + + constructor(client: CosmWasmClient, contractAddress: string) { + this.client = client; + this.contractAddress = contractAddress; + this.getCurrentEpochState = this.getCurrentEpochState.bind(this); + this.getCurrentEpochThreshold = this.getCurrentEpochThreshold.bind(this); + this.getInitialDealers = this.getInitialDealers.bind(this); + this.getDealerDetails = this.getDealerDetails.bind(this); + this.getCurrentDealers = this.getCurrentDealers.bind(this); + this.getPastDealers = this.getPastDealers.bind(this); + this.getDealing = this.getDealing.bind(this); + this.getVerificationKeys = this.getVerificationKeys.bind(this); + } + + getCurrentEpochState = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_current_epoch_state: {} + }); + }; + getCurrentEpochThreshold = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_current_epoch_threshold: {} + }); + }; + getInitialDealers = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_initial_dealers: {} + }); + }; + getDealerDetails = async ({ + dealerAddress + }: { + dealerAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_dealer_details: { + dealer_address: dealerAddress + } + }); + }; + getCurrentDealers = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_current_dealers: { + limit, + start_after: startAfter + } + }); + }; + getPastDealers = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_past_dealers: { + limit, + start_after: startAfter + } + }); + }; + getDealing = async ({ + idx, + limit, + startAfter + }: { + idx: number; + limit?: number; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_dealing: { + idx, + limit, + start_after: startAfter + } + }); + }; + getVerificationKeys = async ({ + epochId, + limit, + startAfter + }: { + epochId: number; + limit?: number; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_verification_keys: { + epoch_id: epochId, + limit, + start_after: startAfter + } + }); + }; +} +export interface CoconutDkgInterface extends CoconutDkgReadOnlyInterface { + contractAddress: string; + sender: string; + registerDealer: ({ + announceAddress, + bteKeyWithProof, + resharing + }: { + announceAddress: string; + bteKeyWithProof: string; + resharing: boolean; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + commitDealing: ({ + dealingBytes, + resharing + }: { + dealingBytes: ContractSafeBytes; + resharing: boolean; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + commitVerificationKeyShare: ({ + resharing, + share + }: { + resharing: boolean; + share: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + verifyVerificationKeyShare: ({ + owner, + resharing + }: { + owner: Addr; + resharing: boolean; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + surpassedThreshold: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + advanceEpochState: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; +} +export class CoconutDkgClient extends CoconutDkgQueryClient implements CoconutDkgInterface { + client: SigningCosmWasmClient; + sender: string; + contractAddress: string; + + constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) { + super(client, contractAddress); + this.client = client; + this.sender = sender; + this.contractAddress = contractAddress; + this.registerDealer = this.registerDealer.bind(this); + this.commitDealing = this.commitDealing.bind(this); + this.commitVerificationKeyShare = this.commitVerificationKeyShare.bind(this); + this.verifyVerificationKeyShare = this.verifyVerificationKeyShare.bind(this); + this.surpassedThreshold = this.surpassedThreshold.bind(this); + this.advanceEpochState = this.advanceEpochState.bind(this); + } + + registerDealer = async ({ + announceAddress, + bteKeyWithProof, + resharing + }: { + announceAddress: string; + bteKeyWithProof: string; + resharing: boolean; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + register_dealer: { + announce_address: announceAddress, + bte_key_with_proof: bteKeyWithProof, + resharing + } + }, fee, memo, _funds); + }; + commitDealing = async ({ + dealingBytes, + resharing + }: { + dealingBytes: ContractSafeBytes; + resharing: boolean; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + commit_dealing: { + dealing_bytes: dealingBytes, + resharing + } + }, fee, memo, _funds); + }; + commitVerificationKeyShare = async ({ + resharing, + share + }: { + resharing: boolean; + share: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + commit_verification_key_share: { + resharing, + share + } + }, fee, memo, _funds); + }; + verifyVerificationKeyShare = async ({ + owner, + resharing + }: { + owner: Addr; + resharing: boolean; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + verify_verification_key_share: { + owner, + resharing + } + }, fee, memo, _funds); + }; + surpassedThreshold = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + surpassed_threshold: {} + }, fee, memo, _funds); + }; + advanceEpochState = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + advance_epoch_state: {} + }, fee, memo, _funds); + }; +} diff --git a/sdk/typescript/codegen/contract-clients/src/CoconutDkg.types.ts b/sdk/typescript/codegen/contract-clients/src/CoconutDkg.types.ts new file mode 100644 index 0000000000..1f90bc5ed3 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/CoconutDkg.types.ts @@ -0,0 +1,154 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +export interface InstantiateMsg { + group_addr: string; + mix_denom: string; + multisig_addr: string; + time_configuration?: TimeConfiguration | null; +} +export interface TimeConfiguration { + dealing_exchange_time_secs: number; + in_progress_time_secs: number; + public_key_submission_time_secs: number; + verification_key_finalization_time_secs: number; + verification_key_submission_time_secs: number; + verification_key_validation_time_secs: number; +} +export type ExecuteMsg = { + register_dealer: { + announce_address: string; + bte_key_with_proof: string; + resharing: boolean; + }; +} | { + commit_dealing: { + dealing_bytes: ContractSafeBytes; + resharing: boolean; + }; +} | { + commit_verification_key_share: { + resharing: boolean; + share: string; + }; +} | { + verify_verification_key_share: { + owner: Addr; + resharing: boolean; + }; +} | { + surpassed_threshold: {}; +} | { + advance_epoch_state: {}; +}; +export type ContractSafeBytes = number[]; +export type Addr = string; +export type QueryMsg = { + get_current_epoch_state: {}; +} | { + get_current_epoch_threshold: {}; +} | { + get_initial_dealers: {}; +} | { + get_dealer_details: { + dealer_address: string; + }; +} | { + get_current_dealers: { + limit?: number | null; + start_after?: string | null; + }; +} | { + get_past_dealers: { + limit?: number | null; + start_after?: string | null; + }; +} | { + get_dealing: { + idx: number; + limit?: number | null; + start_after?: string | null; + }; +} | { + get_verification_keys: { + epoch_id: number; + limit?: number | null; + start_after?: string | null; + }; +}; +export interface MigrateMsg {} +export interface PagedDealerResponse { + dealers: DealerDetails[]; + per_page: number; + start_next_after?: Addr | null; +} +export interface DealerDetails { + address: Addr; + announce_address: string; + assigned_index: number; + bte_public_key_with_proof: string; +} +export type Timestamp = Uint64; +export type Uint64 = number; +export type EpochState = "in_progress" | { + public_key_submission: { + resharing: boolean; + }; +} | { + dealing_exchange: { + resharing: boolean; + }; +} | { + verification_key_submission: { + resharing: boolean; + }; +} | { + verification_key_validation: { + resharing: boolean; + }; +} | { + verification_key_finalization: { + resharing: boolean; + }; +}; +export interface Epoch { + epoch_id: number; + finish_timestamp: Timestamp; + state: EpochState; + time_configuration: TimeConfiguration; +} +export type DealerType = "current" | "past" | "unknown"; +export interface DealerDetailsResponse { + dealer_type: DealerType; + details?: DealerDetails | null; +} +export interface PagedDealingsResponse { + dealings: ContractDealing[]; + per_page: number; + start_next_after?: Addr | null; +} +export interface ContractDealing { + dealer: Addr; + dealing: ContractSafeBytes; +} +export type NullableInitialReplacementData = InitialReplacementData | null; +export interface InitialReplacementData { + initial_dealers: Addr[]; + initial_height: number; +} +export interface PagedVKSharesResponse { + per_page: number; + shares: ContractVKShare[]; + start_next_after?: Addr | null; +} +export interface ContractVKShare { + announce_address: string; + epoch_id: number; + node_index: number; + owner: Addr; + share: string; + verified: boolean; +} \ No newline at end of file diff --git a/sdk/typescript/codegen/contract-clients/src/Cw3FlexMultisig.client.ts b/sdk/typescript/codegen/contract-clients/src/Cw3FlexMultisig.client.ts new file mode 100644 index 0000000000..cfe3b9f76f --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/Cw3FlexMultisig.client.ts @@ -0,0 +1,308 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; +import { StdFee } from "@cosmjs/amino"; +import { Executor, Addr, Duration, Uint128, UncheckedDenom, Threshold, Decimal, InstantiateMsg, UncheckedDepositInfo, ExecuteMsg, Expiration, Timestamp, Uint64, CosmosMsgForEmpty, BankMsg, StakingMsg, DistributionMsg, Binary, IbcMsg, WasmMsg, GovMsg, VoteOption, Vote, Coin, Empty, IbcTimeout, IbcTimeoutBlock, MemberChangedHookMsg, MemberDiff, QueryMsg, MigrateMsg, Cw4Contract, Denom, Config, DepositInfo, Status, ThresholdResponse, ProposalListResponseForEmpty, ProposalResponseForEmpty, VoterListResponse, VoterDetail, VoteListResponse, VoteInfo, VoteResponse, VoterResponse } from "./Cw3FlexMultisig.types"; + +export interface Cw3FlexMultisigReadOnlyInterface { + contractAddress: string; + threshold: () => Promise; + proposal: ({ + proposalId + }: { + proposalId: number; + }) => Promise; + listProposals: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }) => Promise; + reverseProposals: ({ + limit, + startBefore + }: { + limit?: number; + startBefore?: number; + }) => Promise; + vote: ({ + proposalId, + voter + }: { + proposalId: number; + voter: string; + }) => Promise; + listVotes: ({ + limit, + proposalId, + startAfter + }: { + limit?: number; + proposalId: number; + startAfter?: string; + }) => Promise; + voter: ({ + address + }: { + address: string; + }) => Promise; + listVoters: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }) => Promise; + config: () => Promise; +} +export class Cw3FlexMultisigQueryClient implements Cw3FlexMultisigReadOnlyInterface { + client: CosmWasmClient; + contractAddress: string; + + constructor(client: CosmWasmClient, contractAddress: string) { + this.client = client; + this.contractAddress = contractAddress; + this.threshold = this.threshold.bind(this); + this.proposal = this.proposal.bind(this); + this.listProposals = this.listProposals.bind(this); + this.reverseProposals = this.reverseProposals.bind(this); + this.vote = this.vote.bind(this); + this.listVotes = this.listVotes.bind(this); + this.voter = this.voter.bind(this); + this.listVoters = this.listVoters.bind(this); + this.config = this.config.bind(this); + } + + threshold = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + threshold: {} + }); + }; + proposal = async ({ + proposalId + }: { + proposalId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + proposal: { + proposal_id: proposalId + } + }); + }; + listProposals = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + list_proposals: { + limit, + start_after: startAfter + } + }); + }; + reverseProposals = async ({ + limit, + startBefore + }: { + limit?: number; + startBefore?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + reverse_proposals: { + limit, + start_before: startBefore + } + }); + }; + vote = async ({ + proposalId, + voter + }: { + proposalId: number; + voter: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + vote: { + proposal_id: proposalId, + voter + } + }); + }; + listVotes = async ({ + limit, + proposalId, + startAfter + }: { + limit?: number; + proposalId: number; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + list_votes: { + limit, + proposal_id: proposalId, + start_after: startAfter + } + }); + }; + voter = async ({ + address + }: { + address: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + voter: { + address + } + }); + }; + listVoters = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + list_voters: { + limit, + start_after: startAfter + } + }); + }; + config = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + config: {} + }); + }; +} +export interface Cw3FlexMultisigInterface extends Cw3FlexMultisigReadOnlyInterface { + contractAddress: string; + sender: string; + propose: ({ + description, + latest, + msgs, + title + }: { + description: string; + latest?: Expiration; + msgs: CosmosMsgForEmpty[]; + title: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + // vote: ({ + // proposalId, + // vote + // }: { + // proposalId: number; + // vote: Vote; + // }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + execute: ({ + proposalId + }: { + proposalId: number; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + close: ({ + proposalId + }: { + proposalId: number; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + memberChangedHook: ({ + diffs + }: { + diffs: MemberDiff[]; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; +} +export class Cw3FlexMultisigClient extends Cw3FlexMultisigQueryClient implements Cw3FlexMultisigInterface { + client: SigningCosmWasmClient; + sender: string; + contractAddress: string; + + constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) { + super(client, contractAddress); + this.client = client; + this.sender = sender; + this.contractAddress = contractAddress; + this.propose = this.propose.bind(this); + this.vote = this.vote.bind(this); + this.execute = this.execute.bind(this); + this.close = this.close.bind(this); + this.memberChangedHook = this.memberChangedHook.bind(this); + } + + propose = async ({ + description, + latest, + msgs, + title + }: { + description: string; + latest?: Expiration; + msgs: CosmosMsgForEmpty[]; + title: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + propose: { + description, + latest, + msgs, + title + } + }, fee, memo, _funds); + }; + // vote = async ({ + // proposalId, + // vote + // }: { + // proposalId: number; + // vote: Vote; + // }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + // return await this.client.execute(this.sender, this.contractAddress, { + // vote: { + // proposal_id: proposalId, + // vote + // } + // }, fee, memo, _funds); + // }; + execute = async ({ + proposalId + }: { + proposalId: number; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + execute: { + proposal_id: proposalId + } + }, fee, memo, _funds); + }; + close = async ({ + proposalId + }: { + proposalId: number; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + close: { + proposal_id: proposalId + } + }, fee, memo, _funds); + }; + memberChangedHook = async ({ + diffs + }: { + diffs: MemberDiff[]; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + member_changed_hook: { + diffs + } + }, fee, memo, _funds); + }; +} diff --git a/sdk/typescript/codegen/contract-clients/src/Cw3FlexMultisig.types.ts b/sdk/typescript/codegen/contract-clients/src/Cw3FlexMultisig.types.ts new file mode 100644 index 0000000000..570e09b83d --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/Cw3FlexMultisig.types.ts @@ -0,0 +1,355 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +export type Executor = "member" | { + only: Addr; +}; +export type Addr = string; +export type Duration = { + height: number; +} | { + time: number; +}; +export type Uint128 = string; +export type UncheckedDenom = { + native: string; +} | { + cw20: string; +}; +export type Threshold = { + absolute_count: { + weight: number; + }; +} | { + absolute_percentage: { + percentage: Decimal; + }; +} | { + threshold_quorum: { + quorum: Decimal; + threshold: Decimal; + }; +}; +export type Decimal = string; +export interface InstantiateMsg { + coconut_bandwidth_contract_address: string; + coconut_dkg_contract_address: string; + executor?: Executor | null; + group_addr: string; + max_voting_period: Duration; + proposal_deposit?: UncheckedDepositInfo | null; + threshold: Threshold; +} +export interface UncheckedDepositInfo { + amount: Uint128; + denom: UncheckedDenom; + refund_failed_proposals: boolean; +} +export type ExecuteMsg = { + propose: { + description: string; + latest?: Expiration | null; + msgs: CosmosMsgForEmpty[]; + title: string; + }; +} | { + vote: { + proposal_id: number; + vote: Vote; + }; +} | { + execute: { + proposal_id: number; + }; +} | { + close: { + proposal_id: number; + }; +} | { + member_changed_hook: MemberChangedHookMsg; +}; +export type Expiration = { + at_height: number; +} | { + at_time: Timestamp; +} | { + never: {}; +}; +export type Timestamp = Uint64; +export type Uint64 = string; +export type CosmosMsgForEmpty = { + bank: BankMsg; +} | { + custom: Empty; +} | { + staking: StakingMsg; +} | { + distribution: DistributionMsg; +} | { + stargate: { + type_url: string; + value: Binary; + [k: string]: unknown; + }; +} | { + ibc: IbcMsg; +} | { + wasm: WasmMsg; +} | { + gov: GovMsg; +}; +export type BankMsg = { + send: { + amount: Coin[]; + to_address: string; + [k: string]: unknown; + }; +} | { + burn: { + amount: Coin[]; + [k: string]: unknown; + }; +}; +export type StakingMsg = { + delegate: { + amount: Coin; + validator: string; + [k: string]: unknown; + }; +} | { + undelegate: { + amount: Coin; + validator: string; + [k: string]: unknown; + }; +} | { + redelegate: { + amount: Coin; + dst_validator: string; + src_validator: string; + [k: string]: unknown; + }; +}; +export type DistributionMsg = { + set_withdraw_address: { + address: string; + [k: string]: unknown; + }; +} | { + withdraw_delegator_reward: { + validator: string; + [k: string]: unknown; + }; +}; +export type Binary = string; +export type IbcMsg = { + transfer: { + amount: Coin; + channel_id: string; + timeout: IbcTimeout; + to_address: string; + [k: string]: unknown; + }; +} | { + send_packet: { + channel_id: string; + data: Binary; + timeout: IbcTimeout; + [k: string]: unknown; + }; +} | { + close_channel: { + channel_id: string; + [k: string]: unknown; + }; +}; +export type WasmMsg = { + execute: { + contract_addr: string; + funds: Coin[]; + msg: Binary; + [k: string]: unknown; + }; +} | { + instantiate: { + admin?: string | null; + code_id: number; + funds: Coin[]; + label: string; + msg: Binary; + [k: string]: unknown; + }; +} | { + migrate: { + contract_addr: string; + msg: Binary; + new_code_id: number; + [k: string]: unknown; + }; +} | { + update_admin: { + admin: string; + contract_addr: string; + [k: string]: unknown; + }; +} | { + clear_admin: { + contract_addr: string; + [k: string]: unknown; + }; +}; +export type GovMsg = { + vote: { + proposal_id: number; + vote: VoteOption; + [k: string]: unknown; + }; +}; +export type VoteOption = "yes" | "no" | "abstain" | "no_with_veto"; +export type Vote = "yes" | "no" | "abstain" | "veto"; +export interface Coin { + amount: Uint128; + denom: string; + [k: string]: unknown; +} +export interface Empty { + [k: string]: unknown; +} +export interface IbcTimeout { + block?: IbcTimeoutBlock | null; + timestamp?: Timestamp | null; + [k: string]: unknown; +} +export interface IbcTimeoutBlock { + height: number; + revision: number; + [k: string]: unknown; +} +export interface MemberChangedHookMsg { + diffs: MemberDiff[]; +} +export interface MemberDiff { + key: string; + new?: number | null; + old?: number | null; +} +export type QueryMsg = { + threshold: {}; +} | { + proposal: { + proposal_id: number; + }; +} | { + list_proposals: { + limit?: number | null; + start_after?: number | null; + }; +} | { + reverse_proposals: { + limit?: number | null; + start_before?: number | null; + }; +} | { + vote: { + proposal_id: number; + voter: string; + }; +} | { + list_votes: { + limit?: number | null; + proposal_id: number; + start_after?: string | null; + }; +} | { + voter: { + address: string; + }; +} | { + list_voters: { + limit?: number | null; + start_after?: string | null; + }; +} | { + config: {}; +}; +export interface MigrateMsg { + coconut_bandwidth_address: string; + coconut_dkg_address: string; +} +export type Cw4Contract = Addr; +export type Denom = { + native: string; +} | { + cw20: Addr; +}; +export interface Config { + coconut_bandwidth_addr: Addr; + coconut_dkg_addr: Addr; + executor?: Executor | null; + group_addr: Cw4Contract; + max_voting_period: Duration; + proposal_deposit?: DepositInfo | null; + threshold: Threshold; +} +export interface DepositInfo { + amount: Uint128; + denom: Denom; + refund_failed_proposals: boolean; +} +export type Status = "pending" | "open" | "rejected" | "passed" | "executed"; +export type ThresholdResponse = { + absolute_count: { + total_weight: number; + weight: number; + }; +} | { + absolute_percentage: { + percentage: Decimal; + total_weight: number; + }; +} | { + threshold_quorum: { + quorum: Decimal; + threshold: Decimal; + total_weight: number; + }; +}; +export interface ProposalListResponseForEmpty { + proposals: ProposalResponseForEmpty[]; +} +export interface ProposalResponseForEmpty { + deposit?: DepositInfo | null; + description: string; + expires: Expiration; + id: number; + msgs: CosmosMsgForEmpty[]; + proposer: Addr; + status: Status; + threshold: ThresholdResponse; + title: string; +} +export interface VoterListResponse { + voters: VoterDetail[]; +} +export interface VoterDetail { + addr: string; + weight: number; +} +export interface VoteListResponse { + votes: VoteInfo[]; +} +export interface VoteInfo { + proposal_id: number; + vote: Vote; + voter: string; + weight: number; +} +export interface VoteResponse { + vote?: VoteInfo | null; +} +export interface VoterResponse { + weight?: number | null; +} \ No newline at end of file diff --git a/sdk/typescript/codegen/contract-clients/src/Cw4Group.client.ts b/sdk/typescript/codegen/contract-clients/src/Cw4Group.client.ts new file mode 100644 index 0000000000..42482b9aba --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/Cw4Group.client.ts @@ -0,0 +1,188 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; +import { Coin, StdFee } from "@cosmjs/amino"; +import { InstantiateMsg, Member, ExecuteMsg, QueryMsg, MigrateMsg, AdminResponse, HooksResponse, MemberListResponse, MemberResponse, TotalWeightResponse } from "./Cw4Group.types"; + +export interface Cw4GroupReadOnlyInterface { + contractAddress: string; + admin: () => Promise; + totalWeight: ({ + atHeight + }: { + atHeight?: number; + }) => Promise; + listMembers: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }) => Promise; + member: ({ + addr, + atHeight + }: { + addr: string; + atHeight?: number; + }) => Promise; + hooks: () => Promise; +} +export class Cw4GroupQueryClient implements Cw4GroupReadOnlyInterface { + client: CosmWasmClient; + contractAddress: string; + + constructor(client: CosmWasmClient, contractAddress: string) { + this.client = client; + this.contractAddress = contractAddress; + this.admin = this.admin.bind(this); + this.totalWeight = this.totalWeight.bind(this); + this.listMembers = this.listMembers.bind(this); + this.member = this.member.bind(this); + this.hooks = this.hooks.bind(this); + } + + admin = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + admin: {} + }); + }; + totalWeight = async ({ + atHeight + }: { + atHeight?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + total_weight: { + at_height: atHeight + } + }); + }; + listMembers = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + list_members: { + limit, + start_after: startAfter + } + }); + }; + member = async ({ + addr, + atHeight + }: { + addr: string; + atHeight?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + member: { + addr, + at_height: atHeight + } + }); + }; + hooks = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + hooks: {} + }); + }; +} +export interface Cw4GroupInterface extends Cw4GroupReadOnlyInterface { + contractAddress: string; + sender: string; + updateAdmin: ({ + admin + }: { + admin?: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateMembers: ({ + add, + remove + }: { + add: Member[]; + remove: string[]; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + addHook: ({ + addr + }: { + addr: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + removeHook: ({ + addr + }: { + addr: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; +} +export class Cw4GroupClient extends Cw4GroupQueryClient implements Cw4GroupInterface { + client: SigningCosmWasmClient; + sender: string; + contractAddress: string; + + constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) { + super(client, contractAddress); + this.client = client; + this.sender = sender; + this.contractAddress = contractAddress; + this.updateAdmin = this.updateAdmin.bind(this); + this.updateMembers = this.updateMembers.bind(this); + this.addHook = this.addHook.bind(this); + this.removeHook = this.removeHook.bind(this); + } + + updateAdmin = async ({ + admin + }: { + admin?: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_admin: { + admin + } + }, fee, memo, _funds); + }; + updateMembers = async ({ + add, + remove + }: { + add: Member[]; + remove: string[]; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_members: { + add, + remove + } + }, fee, memo, _funds); + }; + addHook = async ({ + addr + }: { + addr: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + add_hook: { + addr + } + }, fee, memo, _funds); + }; + removeHook = async ({ + addr + }: { + addr: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + remove_hook: { + addr + } + }, fee, memo, _funds); + }; +} diff --git a/sdk/typescript/codegen/contract-clients/src/Cw4Group.types.ts b/sdk/typescript/codegen/contract-clients/src/Cw4Group.types.ts new file mode 100644 index 0000000000..6fe03352a2 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/Cw4Group.types.ts @@ -0,0 +1,67 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +export interface InstantiateMsg { + admin?: string | null; + members: Member[]; +} +export interface Member { + addr: string; + weight: number; +} +export type ExecuteMsg = { + update_admin: { + admin?: string | null; + }; +} | { + update_members: { + add: Member[]; + remove: string[]; + }; +} | { + add_hook: { + addr: string; + }; +} | { + remove_hook: { + addr: string; + }; +}; +export type QueryMsg = { + admin: {}; +} | { + total_weight: { + at_height?: number | null; + }; +} | { + list_members: { + limit?: number | null; + start_after?: string | null; + }; +} | { + member: { + addr: string; + at_height?: number | null; + }; +} | { + hooks: {}; +}; +export interface MigrateMsg {} +export interface AdminResponse { + admin?: string | null; +} +export interface HooksResponse { + hooks: string[]; +} +export interface MemberListResponse { + members: Member[]; +} +export interface MemberResponse { + weight?: number | null; +} +export interface TotalWeightResponse { + weight: number; +} \ No newline at end of file diff --git a/sdk/typescript/codegen/contract-clients/src/Mixnet.client.ts b/sdk/typescript/codegen/contract-clients/src/Mixnet.client.ts new file mode 100644 index 0000000000..c775e31a3d --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/Mixnet.client.ts @@ -0,0 +1,1673 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; +import { StdFee } from "@cosmjs/amino"; +import { Decimal, Percent, InstantiateMsg, Duration, InitialRewardingParams, ExecuteMsg, Layer, FamilyHead, MessageSignature, Uint128, ContractStateParams, Coin, IntervalRewardingParamsUpdate, LayerAssignment, MixNodeCostParams, MixNode, MixNodeConfigUpdate, Gateway, GatewayConfigUpdate, QueryMsg, MigrateMsg, Addr, PagedAllDelegationsResponse, Delegation, PagedFamiliesResponse, Family, PagedMembersResponse, MixnodeDetailsByIdentityResponse, MixNodeDetails, MixNodeBond, PendingMixNodeChanges, MixNodeRewarding, ContractVersion, ContractBuildInformation, CurrentIntervalResponse, Interval, MixNodeDelegationResponse, PagedDelegatorDelegationsResponse, EpochState, EpochStatus, EstimatedCurrentEpochRewardResponse, FamilyByHeadResponse, FamilyByLabelResponse, FamilyMembersByHeadResponse, FamilyMembersByLabelResponse, GatewayBondResponse, GatewayBond, PagedGatewayResponse, LayerDistribution, PagedMixnodeBondsResponse, PagedMixnodesDetailsResponse, PagedMixNodeDelegationsResponse, MixnodeDetailsResponse, MixnodeRewardingDetailsResponse, NumberOfPendingEventsResponse, GatewayOwnershipResponse, MixOwnershipResponse, PendingRewardResponse, PendingEpochEventKind, PendingEpochEventResponse, PendingEpochEventData, PendingEpochEventsResponse, PendingEpochEvent, PendingIntervalEventKind, PendingIntervalEventResponse, PendingIntervalEventData, PendingIntervalEventsResponse, PendingIntervalEvent, RewardedSetNodeStatus, PagedRewardedSetResponse, RewardingParams, IntervalRewardParams, String, Uint32, StakeSaturationResponse, ContractState, UnbondedMixnodeResponse, UnbondedMixnode, PagedUnbondedMixnodesResponse } from "./Mixnet.types"; +import { GetCw2ContractVersionResponse } from './types'; +export interface MixnetReadOnlyInterface { + contractAddress: string; + getAllFamiliesPaged: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }) => Promise; + getAllMembersPaged: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }) => Promise; + getFamilyByHead: ({ + head + }: { + head: string; + }) => Promise; + getFamilyByLabel: ({ + label + }: { + label: string; + }) => Promise; + getFamilyMembersByHead: ({ + head + }: { + head: string; + }) => Promise; + getFamilyMembersByLabel: ({ + label + }: { + label: string; + }) => Promise; + getContractVersion: () => Promise; + getCw2ContractVersion: () => Promise; + getRewardingValidatorAddress: () => Promise; + getStateParams: () => Promise; + getState: () => Promise; + getRewardingParams: () => Promise; + getEpochStatus: () => Promise; + getCurrentIntervalDetails: () => Promise; + getRewardedSet: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }) => Promise; + getMixNodeBonds: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }) => Promise; + getMixNodesDetailed: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }) => Promise; + getUnbondedMixNodes: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }) => Promise; + getUnbondedMixNodesByOwner: ({ + limit, + owner, + startAfter + }: { + limit?: number; + owner: string; + startAfter?: number; + }) => Promise; + getUnbondedMixNodesByIdentityKey: ({ + identityKey, + limit, + startAfter + }: { + identityKey: string; + limit?: number; + startAfter?: number; + }) => Promise; + getOwnedMixnode: ({ + address + }: { + address: string; + }) => Promise; + getMixnodeDetails: ({ + mixId + }: { + mixId: number; + }) => Promise; + getMixnodeRewardingDetails: ({ + mixId + }: { + mixId: number; + }) => Promise; + getStakeSaturation: ({ + mixId + }: { + mixId: number; + }) => Promise; + getUnbondedMixNodeInformation: ({ + mixId + }: { + mixId: number; + }) => Promise; + getBondedMixnodeDetailsByIdentity: ({ + mixIdentity + }: { + mixIdentity: string; + }) => Promise; + getLayerDistribution: () => Promise; + getGateways: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }) => Promise; + getGatewayBond: ({ + identity + }: { + identity: string; + }) => Promise; + getOwnedGateway: ({ + address + }: { + address: string; + }) => Promise; + getMixnodeDelegations: ({ + limit, + mixId, + startAfter + }: { + limit?: number; + mixId: number; + startAfter?: string; + }) => Promise; + getDelegatorDelegations: ({ + delegator, + limit, + startAfter + }: { + delegator: string; + limit?: number; + startAfter?: number[][]; + }) => Promise; + getDelegationDetails: ({ + delegator, + mixId, + proxy + }: { + delegator: string; + mixId: number; + proxy?: string; + }) => Promise; + getAllDelegations: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number[][]; + }) => Promise; + getPendingOperatorReward: ({ + address + }: { + address: string; + }) => Promise; + getPendingMixNodeOperatorReward: ({ + mixId + }: { + mixId: number; + }) => Promise; + getPendingDelegatorReward: ({ + address, + mixId, + proxy + }: { + address: string; + mixId: number; + proxy?: string; + }) => Promise; + getEstimatedCurrentEpochOperatorReward: ({ + estimatedPerformance, + mixId + }: { + estimatedPerformance: Percent; + mixId: number; + }) => Promise; + getEstimatedCurrentEpochDelegatorReward: ({ + address, + estimatedPerformance, + mixId, + proxy + }: { + address: string; + estimatedPerformance: Percent; + mixId: number; + proxy?: string; + }) => Promise; + getPendingEpochEvents: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }) => Promise; + getPendingIntervalEvents: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }) => Promise; + getPendingEpochEvent: ({ + eventId + }: { + eventId: number; + }) => Promise; + getPendingIntervalEvent: ({ + eventId + }: { + eventId: number; + }) => Promise; + getNumberOfPendingEvents: () => Promise; + getSigningNonce: ({ + address + }: { + address: string; + }) => Promise; +} +export class MixnetQueryClient implements MixnetReadOnlyInterface { + client: CosmWasmClient; + contractAddress: string; + + constructor(client: CosmWasmClient, contractAddress: string) { + this.client = client; + this.contractAddress = contractAddress; + this.getAllFamiliesPaged = this.getAllFamiliesPaged.bind(this); + this.getAllMembersPaged = this.getAllMembersPaged.bind(this); + this.getFamilyByHead = this.getFamilyByHead.bind(this); + this.getFamilyByLabel = this.getFamilyByLabel.bind(this); + this.getFamilyMembersByHead = this.getFamilyMembersByHead.bind(this); + this.getFamilyMembersByLabel = this.getFamilyMembersByLabel.bind(this); + this.getContractVersion = this.getContractVersion.bind(this); + this.getCw2ContractVersion = this.getCw2ContractVersion.bind(this); + this.getRewardingValidatorAddress = this.getRewardingValidatorAddress.bind(this); + this.getStateParams = this.getStateParams.bind(this); + this.getState = this.getState.bind(this); + this.getRewardingParams = this.getRewardingParams.bind(this); + this.getEpochStatus = this.getEpochStatus.bind(this); + this.getCurrentIntervalDetails = this.getCurrentIntervalDetails.bind(this); + this.getRewardedSet = this.getRewardedSet.bind(this); + this.getMixNodeBonds = this.getMixNodeBonds.bind(this); + this.getMixNodesDetailed = this.getMixNodesDetailed.bind(this); + this.getUnbondedMixNodes = this.getUnbondedMixNodes.bind(this); + this.getUnbondedMixNodesByOwner = this.getUnbondedMixNodesByOwner.bind(this); + this.getUnbondedMixNodesByIdentityKey = this.getUnbondedMixNodesByIdentityKey.bind(this); + this.getOwnedMixnode = this.getOwnedMixnode.bind(this); + this.getMixnodeDetails = this.getMixnodeDetails.bind(this); + this.getMixnodeRewardingDetails = this.getMixnodeRewardingDetails.bind(this); + this.getStakeSaturation = this.getStakeSaturation.bind(this); + this.getUnbondedMixNodeInformation = this.getUnbondedMixNodeInformation.bind(this); + this.getBondedMixnodeDetailsByIdentity = this.getBondedMixnodeDetailsByIdentity.bind(this); + this.getLayerDistribution = this.getLayerDistribution.bind(this); + this.getGateways = this.getGateways.bind(this); + this.getGatewayBond = this.getGatewayBond.bind(this); + this.getOwnedGateway = this.getOwnedGateway.bind(this); + this.getMixnodeDelegations = this.getMixnodeDelegations.bind(this); + this.getDelegatorDelegations = this.getDelegatorDelegations.bind(this); + this.getDelegationDetails = this.getDelegationDetails.bind(this); + this.getAllDelegations = this.getAllDelegations.bind(this); + this.getPendingOperatorReward = this.getPendingOperatorReward.bind(this); + this.getPendingMixNodeOperatorReward = this.getPendingMixNodeOperatorReward.bind(this); + this.getPendingDelegatorReward = this.getPendingDelegatorReward.bind(this); + this.getEstimatedCurrentEpochOperatorReward = this.getEstimatedCurrentEpochOperatorReward.bind(this); + this.getEstimatedCurrentEpochDelegatorReward = this.getEstimatedCurrentEpochDelegatorReward.bind(this); + this.getPendingEpochEvents = this.getPendingEpochEvents.bind(this); + this.getPendingIntervalEvents = this.getPendingIntervalEvents.bind(this); + this.getPendingEpochEvent = this.getPendingEpochEvent.bind(this); + this.getPendingIntervalEvent = this.getPendingIntervalEvent.bind(this); + this.getNumberOfPendingEvents = this.getNumberOfPendingEvents.bind(this); + this.getSigningNonce = this.getSigningNonce.bind(this); + } + + getAllFamiliesPaged = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_all_families_paged: { + limit, + start_after: startAfter + } + }); + }; + getAllMembersPaged = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_all_members_paged: { + limit, + start_after: startAfter + } + }); + }; + getFamilyByHead = async ({ + head + }: { + head: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_family_by_head: { + head + } + }); + }; + getFamilyByLabel = async ({ + label + }: { + label: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_family_by_label: { + label + } + }); + }; + getFamilyMembersByHead = async ({ + head + }: { + head: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_family_members_by_head: { + head + } + }); + }; + getFamilyMembersByLabel = async ({ + label + }: { + label: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_family_members_by_label: { + label + } + }); + }; + getContractVersion = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_contract_version: {} + }); + }; + getCw2ContractVersion = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_cw2_contract_version: {} + }); + }; + getRewardingValidatorAddress = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_rewarding_validator_address: {} + }); + }; + getStateParams = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_state_params: {} + }); + }; + getState = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_state: {} + }); + }; + getRewardingParams = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_rewarding_params: {} + }); + }; + getEpochStatus = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_epoch_status: {} + }); + }; + getCurrentIntervalDetails = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_current_interval_details: {} + }); + }; + getRewardedSet = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_rewarded_set: { + limit, + start_after: startAfter + } + }); + }; + getMixNodeBonds = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_mix_node_bonds: { + limit, + start_after: startAfter + } + }); + }; + getMixNodesDetailed = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_mix_nodes_detailed: { + limit, + start_after: startAfter + } + }); + }; + getUnbondedMixNodes = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_unbonded_mix_nodes: { + limit, + start_after: startAfter + } + }); + }; + getUnbondedMixNodesByOwner = async ({ + limit, + owner, + startAfter + }: { + limit?: number; + owner: string; + startAfter?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_unbonded_mix_nodes_by_owner: { + limit, + owner, + start_after: startAfter + } + }); + }; + getUnbondedMixNodesByIdentityKey = async ({ + identityKey, + limit, + startAfter + }: { + identityKey: string; + limit?: number; + startAfter?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_unbonded_mix_nodes_by_identity_key: { + identity_key: identityKey, + limit, + start_after: startAfter + } + }); + }; + getOwnedMixnode = async ({ + address + }: { + address: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_owned_mixnode: { + address + } + }); + }; + getMixnodeDetails = async ({ + mixId + }: { + mixId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_mixnode_details: { + mix_id: mixId + } + }); + }; + getMixnodeRewardingDetails = async ({ + mixId + }: { + mixId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_mixnode_rewarding_details: { + mix_id: mixId + } + }); + }; + getStakeSaturation = async ({ + mixId + }: { + mixId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_stake_saturation: { + mix_id: mixId + } + }); + }; + getUnbondedMixNodeInformation = async ({ + mixId + }: { + mixId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_unbonded_mix_node_information: { + mix_id: mixId + } + }); + }; + getBondedMixnodeDetailsByIdentity = async ({ + mixIdentity + }: { + mixIdentity: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_bonded_mixnode_details_by_identity: { + mix_identity: mixIdentity + } + }); + }; + getLayerDistribution = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_layer_distribution: {} + }); + }; + getGateways = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_gateways: { + limit, + start_after: startAfter + } + }); + }; + getGatewayBond = async ({ + identity + }: { + identity: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_gateway_bond: { + identity + } + }); + }; + getOwnedGateway = async ({ + address + }: { + address: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_owned_gateway: { + address + } + }); + }; + getMixnodeDelegations = async ({ + limit, + mixId, + startAfter + }: { + limit?: number; + mixId: number; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_mixnode_delegations: { + limit, + mix_id: mixId, + start_after: startAfter + } + }); + }; + getDelegatorDelegations = async ({ + delegator, + limit, + startAfter + }: { + delegator: string; + limit?: number; + startAfter?: number[][]; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_delegator_delegations: { + delegator, + limit, + start_after: startAfter + } + }); + }; + getDelegationDetails = async ({ + delegator, + mixId, + proxy + }: { + delegator: string; + mixId: number; + proxy?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_delegation_details: { + delegator, + mix_id: mixId, + proxy + } + }); + }; + getAllDelegations = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number[][]; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_all_delegations: { + limit, + start_after: startAfter + } + }); + }; + getPendingOperatorReward = async ({ + address + }: { + address: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_pending_operator_reward: { + address + } + }); + }; + getPendingMixNodeOperatorReward = async ({ + mixId + }: { + mixId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_pending_mix_node_operator_reward: { + mix_id: mixId + } + }); + }; + getPendingDelegatorReward = async ({ + address, + mixId, + proxy + }: { + address: string; + mixId: number; + proxy?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_pending_delegator_reward: { + address, + mix_id: mixId, + proxy + } + }); + }; + getEstimatedCurrentEpochOperatorReward = async ({ + estimatedPerformance, + mixId + }: { + estimatedPerformance: Percent; + mixId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_estimated_current_epoch_operator_reward: { + estimated_performance: estimatedPerformance, + mix_id: mixId + } + }); + }; + getEstimatedCurrentEpochDelegatorReward = async ({ + address, + estimatedPerformance, + mixId, + proxy + }: { + address: string; + estimatedPerformance: Percent; + mixId: number; + proxy?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_estimated_current_epoch_delegator_reward: { + address, + estimated_performance: estimatedPerformance, + mix_id: mixId, + proxy + } + }); + }; + getPendingEpochEvents = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_pending_epoch_events: { + limit, + start_after: startAfter + } + }); + }; + getPendingIntervalEvents = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_pending_interval_events: { + limit, + start_after: startAfter + } + }); + }; + getPendingEpochEvent = async ({ + eventId + }: { + eventId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_pending_epoch_event: { + event_id: eventId + } + }); + }; + getPendingIntervalEvent = async ({ + eventId + }: { + eventId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_pending_interval_event: { + event_id: eventId + } + }); + }; + getNumberOfPendingEvents = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_number_of_pending_events: {} + }); + }; + getSigningNonce = async ({ + address + }: { + address: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_signing_nonce: { + address + } + }); + }; +} +export interface MixnetInterface extends MixnetReadOnlyInterface { + contractAddress: string; + sender: string; + assignNodeLayer: ({ + layer, + mixId + }: { + layer: Layer; + mixId: number; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + createFamily: ({ + label + }: { + label: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + joinFamily: ({ + familyHead, + joinPermit + }: { + familyHead: FamilyHead; + joinPermit: MessageSignature; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + leaveFamily: ({ + familyHead + }: { + familyHead: FamilyHead; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + kickFamilyMember: ({ + member + }: { + member: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + createFamilyOnBehalf: ({ + label, + ownerAddress + }: { + label: string; + ownerAddress: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + joinFamilyOnBehalf: ({ + familyHead, + joinPermit, + memberAddress + }: { + familyHead: FamilyHead; + joinPermit: MessageSignature; + memberAddress: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + leaveFamilyOnBehalf: ({ + familyHead, + memberAddress + }: { + familyHead: FamilyHead; + memberAddress: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + kickFamilyMemberOnBehalf: ({ + headAddress, + member + }: { + headAddress: string; + member: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateRewardingValidatorAddress: ({ + address + }: { + address: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateContractStateParams: ({ + updatedParameters + }: { + updatedParameters: ContractStateParams; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateActiveSetSize: ({ + activeSetSize, + forceImmediately + }: { + activeSetSize: number; + forceImmediately: boolean; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateRewardingParams: ({ + forceImmediately, + updatedParams + }: { + forceImmediately: boolean; + updatedParams: IntervalRewardingParamsUpdate; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateIntervalConfig: ({ + epochDurationSecs, + epochsInInterval, + forceImmediately + }: { + epochDurationSecs: number; + epochsInInterval: number; + forceImmediately: boolean; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + beginEpochTransition: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + advanceCurrentEpoch: ({ + expectedActiveSetSize, + newRewardedSet + }: { + expectedActiveSetSize: number; + newRewardedSet: LayerAssignment[]; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + reconcileEpochEvents: ({ + limit + }: { + limit?: number; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + bondMixnode: ({ + costParams, + mixNode, + ownerSignature + }: { + costParams: MixNodeCostParams; + mixNode: MixNode; + ownerSignature: MessageSignature; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + bondMixnodeOnBehalf: ({ + costParams, + mixNode, + owner, + ownerSignature + }: { + costParams: MixNodeCostParams; + mixNode: MixNode; + owner: string; + ownerSignature: MessageSignature; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + pledgeMore: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + pledgeMoreOnBehalf: ({ + owner + }: { + owner: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + decreasePledge: ({ + decreaseBy + }: { + decreaseBy: Coin; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + decreasePledgeOnBehalf: ({ + decreaseBy, + owner + }: { + decreaseBy: Coin; + owner: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + unbondMixnode: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + unbondMixnodeOnBehalf: ({ + owner + }: { + owner: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateMixnodeCostParams: ({ + newCosts + }: { + newCosts: MixNodeCostParams; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateMixnodeCostParamsOnBehalf: ({ + newCosts, + owner + }: { + newCosts: MixNodeCostParams; + owner: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateMixnodeConfig: ({ + newConfig + }: { + newConfig: MixNodeConfigUpdate; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateMixnodeConfigOnBehalf: ({ + newConfig, + owner + }: { + newConfig: MixNodeConfigUpdate; + owner: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + bondGateway: ({ + gateway, + ownerSignature + }: { + gateway: Gateway; + ownerSignature: MessageSignature; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + bondGatewayOnBehalf: ({ + gateway, + owner, + ownerSignature + }: { + gateway: Gateway; + owner: string; + ownerSignature: MessageSignature; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + unbondGateway: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + unbondGatewayOnBehalf: ({ + owner + }: { + owner: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateGatewayConfig: ({ + newConfig + }: { + newConfig: GatewayConfigUpdate; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateGatewayConfigOnBehalf: ({ + newConfig, + owner + }: { + newConfig: GatewayConfigUpdate; + owner: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + delegateToMixnode: ({ + mixId + }: { + mixId: number; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + delegateToMixnodeOnBehalf: ({ + delegate, + mixId + }: { + delegate: string; + mixId: number; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + undelegateFromMixnode: ({ + mixId + }: { + mixId: number; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + undelegateFromMixnodeOnBehalf: ({ + delegate, + mixId + }: { + delegate: string; + mixId: number; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + rewardMixnode: ({ + mixId, + performance + }: { + mixId: number; + performance: Percent; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + withdrawOperatorReward: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + withdrawOperatorRewardOnBehalf: ({ + owner + }: { + owner: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + withdrawDelegatorReward: ({ + mixId + }: { + mixId: number; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + withdrawDelegatorRewardOnBehalf: ({ + mixId, + owner + }: { + mixId: number; + owner: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; +} +export class MixnetClient extends MixnetQueryClient implements MixnetInterface { + client: SigningCosmWasmClient; + sender: string; + contractAddress: string; + + constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) { + super(client, contractAddress); + this.client = client; + this.sender = sender; + this.contractAddress = contractAddress; + this.assignNodeLayer = this.assignNodeLayer.bind(this); + this.createFamily = this.createFamily.bind(this); + this.joinFamily = this.joinFamily.bind(this); + this.leaveFamily = this.leaveFamily.bind(this); + this.kickFamilyMember = this.kickFamilyMember.bind(this); + this.createFamilyOnBehalf = this.createFamilyOnBehalf.bind(this); + this.joinFamilyOnBehalf = this.joinFamilyOnBehalf.bind(this); + this.leaveFamilyOnBehalf = this.leaveFamilyOnBehalf.bind(this); + this.kickFamilyMemberOnBehalf = this.kickFamilyMemberOnBehalf.bind(this); + this.updateRewardingValidatorAddress = this.updateRewardingValidatorAddress.bind(this); + this.updateContractStateParams = this.updateContractStateParams.bind(this); + this.updateActiveSetSize = this.updateActiveSetSize.bind(this); + this.updateRewardingParams = this.updateRewardingParams.bind(this); + this.updateIntervalConfig = this.updateIntervalConfig.bind(this); + this.beginEpochTransition = this.beginEpochTransition.bind(this); + this.advanceCurrentEpoch = this.advanceCurrentEpoch.bind(this); + this.reconcileEpochEvents = this.reconcileEpochEvents.bind(this); + this.bondMixnode = this.bondMixnode.bind(this); + this.bondMixnodeOnBehalf = this.bondMixnodeOnBehalf.bind(this); + this.pledgeMore = this.pledgeMore.bind(this); + this.pledgeMoreOnBehalf = this.pledgeMoreOnBehalf.bind(this); + this.decreasePledge = this.decreasePledge.bind(this); + this.decreasePledgeOnBehalf = this.decreasePledgeOnBehalf.bind(this); + this.unbondMixnode = this.unbondMixnode.bind(this); + this.unbondMixnodeOnBehalf = this.unbondMixnodeOnBehalf.bind(this); + this.updateMixnodeCostParams = this.updateMixnodeCostParams.bind(this); + this.updateMixnodeCostParamsOnBehalf = this.updateMixnodeCostParamsOnBehalf.bind(this); + this.updateMixnodeConfig = this.updateMixnodeConfig.bind(this); + this.updateMixnodeConfigOnBehalf = this.updateMixnodeConfigOnBehalf.bind(this); + this.bondGateway = this.bondGateway.bind(this); + this.bondGatewayOnBehalf = this.bondGatewayOnBehalf.bind(this); + this.unbondGateway = this.unbondGateway.bind(this); + this.unbondGatewayOnBehalf = this.unbondGatewayOnBehalf.bind(this); + this.updateGatewayConfig = this.updateGatewayConfig.bind(this); + this.updateGatewayConfigOnBehalf = this.updateGatewayConfigOnBehalf.bind(this); + this.delegateToMixnode = this.delegateToMixnode.bind(this); + this.delegateToMixnodeOnBehalf = this.delegateToMixnodeOnBehalf.bind(this); + this.undelegateFromMixnode = this.undelegateFromMixnode.bind(this); + this.undelegateFromMixnodeOnBehalf = this.undelegateFromMixnodeOnBehalf.bind(this); + this.rewardMixnode = this.rewardMixnode.bind(this); + this.withdrawOperatorReward = this.withdrawOperatorReward.bind(this); + this.withdrawOperatorRewardOnBehalf = this.withdrawOperatorRewardOnBehalf.bind(this); + this.withdrawDelegatorReward = this.withdrawDelegatorReward.bind(this); + this.withdrawDelegatorRewardOnBehalf = this.withdrawDelegatorRewardOnBehalf.bind(this); + } + + assignNodeLayer = async ({ + layer, + mixId + }: { + layer: Layer; + mixId: number; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + assign_node_layer: { + layer, + mix_id: mixId + } + }, fee, memo, _funds); + }; + createFamily = async ({ + label + }: { + label: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + create_family: { + label + } + }, fee, memo, _funds); + }; + joinFamily = async ({ + familyHead, + joinPermit + }: { + familyHead: FamilyHead; + joinPermit: MessageSignature; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + join_family: { + family_head: familyHead, + join_permit: joinPermit + } + }, fee, memo, _funds); + }; + leaveFamily = async ({ + familyHead + }: { + familyHead: FamilyHead; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + leave_family: { + family_head: familyHead + } + }, fee, memo, _funds); + }; + kickFamilyMember = async ({ + member + }: { + member: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + kick_family_member: { + member + } + }, fee, memo, _funds); + }; + createFamilyOnBehalf = async ({ + label, + ownerAddress + }: { + label: string; + ownerAddress: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + create_family_on_behalf: { + label, + owner_address: ownerAddress + } + }, fee, memo, _funds); + }; + joinFamilyOnBehalf = async ({ + familyHead, + joinPermit, + memberAddress + }: { + familyHead: FamilyHead; + joinPermit: MessageSignature; + memberAddress: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + join_family_on_behalf: { + family_head: familyHead, + join_permit: joinPermit, + member_address: memberAddress + } + }, fee, memo, _funds); + }; + leaveFamilyOnBehalf = async ({ + familyHead, + memberAddress + }: { + familyHead: FamilyHead; + memberAddress: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + leave_family_on_behalf: { + family_head: familyHead, + member_address: memberAddress + } + }, fee, memo, _funds); + }; + kickFamilyMemberOnBehalf = async ({ + headAddress, + member + }: { + headAddress: string; + member: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + kick_family_member_on_behalf: { + head_address: headAddress, + member + } + }, fee, memo, _funds); + }; + updateRewardingValidatorAddress = async ({ + address + }: { + address: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_rewarding_validator_address: { + address + } + }, fee, memo, _funds); + }; + updateContractStateParams = async ({ + updatedParameters + }: { + updatedParameters: ContractStateParams; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_contract_state_params: { + updated_parameters: updatedParameters + } + }, fee, memo, _funds); + }; + updateActiveSetSize = async ({ + activeSetSize, + forceImmediately + }: { + activeSetSize: number; + forceImmediately: boolean; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_active_set_size: { + active_set_size: activeSetSize, + force_immediately: forceImmediately + } + }, fee, memo, _funds); + }; + updateRewardingParams = async ({ + forceImmediately, + updatedParams + }: { + forceImmediately: boolean; + updatedParams: IntervalRewardingParamsUpdate; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_rewarding_params: { + force_immediately: forceImmediately, + updated_params: updatedParams + } + }, fee, memo, _funds); + }; + updateIntervalConfig = async ({ + epochDurationSecs, + epochsInInterval, + forceImmediately + }: { + epochDurationSecs: number; + epochsInInterval: number; + forceImmediately: boolean; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_interval_config: { + epoch_duration_secs: epochDurationSecs, + epochs_in_interval: epochsInInterval, + force_immediately: forceImmediately + } + }, fee, memo, _funds); + }; + beginEpochTransition = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + begin_epoch_transition: {} + }, fee, memo, _funds); + }; + advanceCurrentEpoch = async ({ + expectedActiveSetSize, + newRewardedSet + }: { + expectedActiveSetSize: number; + newRewardedSet: LayerAssignment[]; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + advance_current_epoch: { + expected_active_set_size: expectedActiveSetSize, + new_rewarded_set: newRewardedSet + } + }, fee, memo, _funds); + }; + reconcileEpochEvents = async ({ + limit + }: { + limit?: number; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + reconcile_epoch_events: { + limit + } + }, fee, memo, _funds); + }; + bondMixnode = async ({ + costParams, + mixNode, + ownerSignature + }: { + costParams: MixNodeCostParams; + mixNode: MixNode; + ownerSignature: MessageSignature; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + bond_mixnode: { + cost_params: costParams, + mix_node: mixNode, + owner_signature: ownerSignature + } + }, fee, memo, _funds); + }; + bondMixnodeOnBehalf = async ({ + costParams, + mixNode, + owner, + ownerSignature + }: { + costParams: MixNodeCostParams; + mixNode: MixNode; + owner: string; + ownerSignature: MessageSignature; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + bond_mixnode_on_behalf: { + cost_params: costParams, + mix_node: mixNode, + owner, + owner_signature: ownerSignature + } + }, fee, memo, _funds); + }; + pledgeMore = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + pledge_more: {} + }, fee, memo, _funds); + }; + pledgeMoreOnBehalf = async ({ + owner + }: { + owner: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + pledge_more_on_behalf: { + owner + } + }, fee, memo, _funds); + }; + decreasePledge = async ({ + decreaseBy + }: { + decreaseBy: Coin; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + decrease_pledge: { + decrease_by: decreaseBy + } + }, fee, memo, _funds); + }; + decreasePledgeOnBehalf = async ({ + decreaseBy, + owner + }: { + decreaseBy: Coin; + owner: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + decrease_pledge_on_behalf: { + decrease_by: decreaseBy, + owner + } + }, fee, memo, _funds); + }; + unbondMixnode = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + unbond_mixnode: {} + }, fee, memo, _funds); + }; + unbondMixnodeOnBehalf = async ({ + owner + }: { + owner: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + unbond_mixnode_on_behalf: { + owner + } + }, fee, memo, _funds); + }; + updateMixnodeCostParams = async ({ + newCosts + }: { + newCosts: MixNodeCostParams; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_mixnode_cost_params: { + new_costs: newCosts + } + }, fee, memo, _funds); + }; + updateMixnodeCostParamsOnBehalf = async ({ + newCosts, + owner + }: { + newCosts: MixNodeCostParams; + owner: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_mixnode_cost_params_on_behalf: { + new_costs: newCosts, + owner + } + }, fee, memo, _funds); + }; + updateMixnodeConfig = async ({ + newConfig + }: { + newConfig: MixNodeConfigUpdate; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_mixnode_config: { + new_config: newConfig + } + }, fee, memo, _funds); + }; + updateMixnodeConfigOnBehalf = async ({ + newConfig, + owner + }: { + newConfig: MixNodeConfigUpdate; + owner: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_mixnode_config_on_behalf: { + new_config: newConfig, + owner + } + }, fee, memo, _funds); + }; + bondGateway = async ({ + gateway, + ownerSignature + }: { + gateway: Gateway; + ownerSignature: MessageSignature; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + bond_gateway: { + gateway, + owner_signature: ownerSignature + } + }, fee, memo, _funds); + }; + bondGatewayOnBehalf = async ({ + gateway, + owner, + ownerSignature + }: { + gateway: Gateway; + owner: string; + ownerSignature: MessageSignature; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + bond_gateway_on_behalf: { + gateway, + owner, + owner_signature: ownerSignature + } + }, fee, memo, _funds); + }; + unbondGateway = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + unbond_gateway: {} + }, fee, memo, _funds); + }; + unbondGatewayOnBehalf = async ({ + owner + }: { + owner: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + unbond_gateway_on_behalf: { + owner + } + }, fee, memo, _funds); + }; + updateGatewayConfig = async ({ + newConfig + }: { + newConfig: GatewayConfigUpdate; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_gateway_config: { + new_config: newConfig + } + }, fee, memo, _funds); + }; + updateGatewayConfigOnBehalf = async ({ + newConfig, + owner + }: { + newConfig: GatewayConfigUpdate; + owner: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_gateway_config_on_behalf: { + new_config: newConfig, + owner + } + }, fee, memo, _funds); + }; + delegateToMixnode = async ({ + mixId + }: { + mixId: number; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + delegate_to_mixnode: { + mix_id: mixId + } + }, fee, memo, _funds); + }; + delegateToMixnodeOnBehalf = async ({ + delegate, + mixId + }: { + delegate: string; + mixId: number; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + delegate_to_mixnode_on_behalf: { + delegate, + mix_id: mixId + } + }, fee, memo, _funds); + }; + undelegateFromMixnode = async ({ + mixId + }: { + mixId: number; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + undelegate_from_mixnode: { + mix_id: mixId + } + }, fee, memo, _funds); + }; + undelegateFromMixnodeOnBehalf = async ({ + delegate, + mixId + }: { + delegate: string; + mixId: number; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + undelegate_from_mixnode_on_behalf: { + delegate, + mix_id: mixId + } + }, fee, memo, _funds); + }; + rewardMixnode = async ({ + mixId, + performance + }: { + mixId: number; + performance: Percent; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + reward_mixnode: { + mix_id: mixId, + performance + } + }, fee, memo, _funds); + }; + withdrawOperatorReward = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + withdraw_operator_reward: {} + }, fee, memo, _funds); + }; + withdrawOperatorRewardOnBehalf = async ({ + owner + }: { + owner: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + withdraw_operator_reward_on_behalf: { + owner + } + }, fee, memo, _funds); + }; + withdrawDelegatorReward = async ({ + mixId + }: { + mixId: number; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + withdraw_delegator_reward: { + mix_id: mixId + } + }, fee, memo, _funds); + }; + withdrawDelegatorRewardOnBehalf = async ({ + mixId, + owner + }: { + mixId: number; + owner: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + withdraw_delegator_reward_on_behalf: { + mix_id: mixId, + owner + } + }, fee, memo, _funds); + }; +} diff --git a/sdk/typescript/codegen/contract-clients/src/Mixnet.types.ts b/sdk/typescript/codegen/contract-clients/src/Mixnet.types.ts new file mode 100644 index 0000000000..f0630f673f --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/Mixnet.types.ts @@ -0,0 +1,799 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +export type Decimal = string; +export type Percent = Decimal; + +/** + * This instantiates the contract. + */ +export interface InstantiateMsg { + epoch_duration: Duration; + epochs_in_interval: number; + initial_rewarding_params: InitialRewardingParams; + rewarding_denom: string; + rewarding_validator_address: string; + vesting_contract_address: string; +} +export interface Duration { + nanos: number; + secs: number; + [k: string]: unknown; +} +export interface InitialRewardingParams { + active_set_size: number; + active_set_work_factor: Decimal; + initial_reward_pool: Decimal; + initial_staking_supply: Decimal; + interval_pool_emission: Percent; + rewarded_set_size: number; + staking_supply_scale_factor: Percent; + sybil_resistance: Percent; +} +export type ExecuteMsg = { + assign_node_layer: { + layer: Layer; + mix_id: number; + }; +} | { + create_family: { + label: string; + }; +} | { + join_family: { + family_head: FamilyHead; + join_permit: MessageSignature; + }; +} | { + leave_family: { + family_head: FamilyHead; + }; +} | { + kick_family_member: { + member: string; + }; +} | { + create_family_on_behalf: { + label: string; + owner_address: string; + }; +} | { + join_family_on_behalf: { + family_head: FamilyHead; + join_permit: MessageSignature; + member_address: string; + }; +} | { + leave_family_on_behalf: { + family_head: FamilyHead; + member_address: string; + }; +} | { + kick_family_member_on_behalf: { + head_address: string; + member: string; + }; +} | { + update_rewarding_validator_address: { + address: string; + }; +} | { + update_contract_state_params: { + updated_parameters: ContractStateParams; + }; +} | { + update_active_set_size: { + active_set_size: number; + force_immediately: boolean; + }; +} | { + update_rewarding_params: { + force_immediately: boolean; + updated_params: IntervalRewardingParamsUpdate; + }; +} | { + update_interval_config: { + epoch_duration_secs: number; + epochs_in_interval: number; + force_immediately: boolean; + }; +} | { + begin_epoch_transition: {}; +} | { + advance_current_epoch: { + expected_active_set_size: number; + new_rewarded_set: LayerAssignment[]; + }; +} | { + reconcile_epoch_events: { + limit?: number | null; + }; +} | { + bond_mixnode: { + cost_params: MixNodeCostParams; + mix_node: MixNode; + owner_signature: MessageSignature; + }; +} | { + bond_mixnode_on_behalf: { + cost_params: MixNodeCostParams; + mix_node: MixNode; + owner: string; + owner_signature: MessageSignature; + }; +} | { + pledge_more: {}; +} | { + pledge_more_on_behalf: { + owner: string; + }; +} | { + decrease_pledge: { + decrease_by: Coin; + }; +} | { + decrease_pledge_on_behalf: { + decrease_by: Coin; + owner: string; + }; +} | { + unbond_mixnode: {}; +} | { + unbond_mixnode_on_behalf: { + owner: string; + }; +} | { + update_mixnode_cost_params: { + new_costs: MixNodeCostParams; + }; +} | { + update_mixnode_cost_params_on_behalf: { + new_costs: MixNodeCostParams; + owner: string; + }; +} | { + update_mixnode_config: { + new_config: MixNodeConfigUpdate; + }; +} | { + update_mixnode_config_on_behalf: { + new_config: MixNodeConfigUpdate; + owner: string; + }; +} | { + bond_gateway: { + gateway: Gateway; + owner_signature: MessageSignature; + }; +} | { + bond_gateway_on_behalf: { + gateway: Gateway; + owner: string; + owner_signature: MessageSignature; + }; +} | { + unbond_gateway: {}; +} | { + unbond_gateway_on_behalf: { + owner: string; + }; +} | { + update_gateway_config: { + new_config: GatewayConfigUpdate; + }; +} | { + update_gateway_config_on_behalf: { + new_config: GatewayConfigUpdate; + owner: string; + }; +} | { + delegate_to_mixnode: { + mix_id: number; + }; +} | { + delegate_to_mixnode_on_behalf: { + delegate: string; + mix_id: number; + }; +} | { + undelegate_from_mixnode: { + mix_id: number; + }; +} | { + undelegate_from_mixnode_on_behalf: { + delegate: string; + mix_id: number; + }; +} | { + reward_mixnode: { + mix_id: number; + performance: Percent; + }; +} | { + withdraw_operator_reward: {}; +} | { + withdraw_operator_reward_on_behalf: { + owner: string; + }; +} | { + withdraw_delegator_reward: { + mix_id: number; + }; +} | { + withdraw_delegator_reward_on_behalf: { + mix_id: number; + owner: string; + }; +}; +export type Layer = "One" | "Two" | "Three"; +export type FamilyHead = string; +export type MessageSignature = number[]; +export type Uint128 = string; +export interface ContractStateParams { + minimum_gateway_pledge: Coin; + minimum_mixnode_delegation?: Coin | null; + minimum_mixnode_pledge: Coin; +} +export interface Coin { + amount: Uint128; + denom: string; + [k: string]: unknown; +} +export interface IntervalRewardingParamsUpdate { + active_set_work_factor?: Decimal | null; + interval_pool_emission?: Percent | null; + reward_pool?: Decimal | null; + rewarded_set_size?: number | null; + staking_supply?: Decimal | null; + staking_supply_scale_factor?: Percent | null; + sybil_resistance_percent?: Percent | null; +} +export interface LayerAssignment { + layer: Layer; + mix_id: number; +} +export interface MixNodeCostParams { + interval_operating_cost: Coin; + profit_margin_percent: Percent; +} +export interface MixNode { + host: string; + http_api_port: number; + identity_key: string; + mix_port: number; + sphinx_key: string; + verloc_port: number; + version: string; +} +export interface MixNodeConfigUpdate { + host: string; + http_api_port: number; + mix_port: number; + verloc_port: number; + version: string; +} +export interface Gateway { + clients_port: number; + host: string; + identity_key: string; + location: string; + mix_port: number; + sphinx_key: string; + version: string; +} +export interface GatewayConfigUpdate { + clients_port: number; + host: string; + location: string; + mix_port: number; + version: string; +} +export type QueryMsg = { + get_all_families_paged: { + limit?: number | null; + start_after?: string | null; + }; +} | { + get_all_members_paged: { + limit?: number | null; + start_after?: string | null; + }; +} | { + get_family_by_head: { + head: string; + }; +} | { + get_family_by_label: { + label: string; + }; +} | { + get_family_members_by_head: { + head: string; + }; +} | { + get_family_members_by_label: { + label: string; + }; +} | { + get_contract_version: {}; +} | { + get_cw2_contract_version: {}; +} | { + get_rewarding_validator_address: {}; +} | { + get_state_params: {}; +} | { + get_state: {}; +} | { + get_rewarding_params: {}; +} | { + get_epoch_status: {}; +} | { + get_current_interval_details: {}; +} | { + get_rewarded_set: { + limit?: number | null; + start_after?: number | null; + }; +} | { + get_mix_node_bonds: { + limit?: number | null; + start_after?: number | null; + }; +} | { + get_mix_nodes_detailed: { + limit?: number | null; + start_after?: number | null; + }; +} | { + get_unbonded_mix_nodes: { + limit?: number | null; + start_after?: number | null; + }; +} | { + get_unbonded_mix_nodes_by_owner: { + limit?: number | null; + owner: string; + start_after?: number | null; + }; +} | { + get_unbonded_mix_nodes_by_identity_key: { + identity_key: string; + limit?: number | null; + start_after?: number | null; + }; +} | { + get_owned_mixnode: { + address: string; + }; +} | { + get_mixnode_details: { + mix_id: number; + }; +} | { + get_mixnode_rewarding_details: { + mix_id: number; + }; +} | { + get_stake_saturation: { + mix_id: number; + }; +} | { + get_unbonded_mix_node_information: { + mix_id: number; + }; +} | { + get_bonded_mixnode_details_by_identity: { + mix_identity: string; + }; +} | { + get_layer_distribution: {}; +} | { + get_gateways: { + limit?: number | null; + start_after?: string | null; + }; +} | { + get_gateway_bond: { + identity: string; + }; +} | { + get_owned_gateway: { + address: string; + }; +} | { + get_mixnode_delegations: { + limit?: number | null; + mix_id: number; + start_after?: string | null; + }; +} | { + get_delegator_delegations: { + delegator: string; + limit?: number | null; + start_after?: [number, string] | null; + }; +} | { + get_delegation_details: { + delegator: string; + mix_id: number; + proxy?: string | null; + }; +} | { + get_all_delegations: { + limit?: number | null; + start_after?: [number, string] | null; + }; +} | { + get_pending_operator_reward: { + address: string; + }; +} | { + get_pending_mix_node_operator_reward: { + mix_id: number; + }; +} | { + get_pending_delegator_reward: { + address: string; + mix_id: number; + proxy?: string | null; + }; +} | { + get_estimated_current_epoch_operator_reward: { + estimated_performance: Percent; + mix_id: number; + }; +} | { + get_estimated_current_epoch_delegator_reward: { + address: string; + estimated_performance: Percent; + mix_id: number; + proxy?: string | null; + }; +} | { + get_pending_epoch_events: { + limit?: number | null; + start_after?: number | null; + }; +} | { + get_pending_interval_events: { + limit?: number | null; + start_after?: number | null; + }; +} | { + get_pending_epoch_event: { + event_id: number; + }; +} | { + get_pending_interval_event: { + event_id: number; + }; +} | { + get_number_of_pending_events: {}; +} | { + get_signing_nonce: { + address: string; + }; +}; +export interface MigrateMsg { + vesting_contract_address?: string | null; +} +export type Addr = string; +export interface PagedAllDelegationsResponse { + delegations: Delegation[]; + start_next_after?: [number, string] | null; +} +export interface Delegation { + amount: Coin; + cumulative_reward_ratio: Decimal; + height: number; + mix_id: number; + owner: Addr; + proxy?: Addr | null; +} +export interface PagedFamiliesResponse { + families: Family[]; + start_next_after?: string | null; +} +export interface Family { + head: FamilyHead; + label: string; + proxy?: string | null; +} +export interface PagedMembersResponse { + members: [string, FamilyHead][]; + start_next_after?: string | null; +} +export interface MixnodeDetailsByIdentityResponse { + identity_key: string; + mixnode_details?: MixNodeDetails | null; +} +export interface MixNodeDetails { + bond_information: MixNodeBond; + pending_changes?: PendingMixNodeChanges; + rewarding_details: MixNodeRewarding; +} +export interface MixNodeBond { + bonding_height: number; + is_unbonding: boolean; + layer: Layer; + mix_id: number; + mix_node: MixNode; + original_pledge: Coin; + owner: Addr; + proxy?: Addr | null; +} +export interface PendingMixNodeChanges { + pledge_change?: number | null; +} +export interface MixNodeRewarding { + cost_params: MixNodeCostParams; + delegates: Decimal; + last_rewarded_epoch: number; + operator: Decimal; + total_unit_reward: Decimal; + unique_delegations: number; + unit_delegation: Decimal; +} +export interface ContractVersion { + contract: string; + version: string; +} +export interface ContractBuildInformation { + build_timestamp: string; + build_version: string; + commit_branch: string; + commit_sha: string; + commit_timestamp: string; + rustc_version: string; +} +export interface CurrentIntervalResponse { + current_blocktime: number; + interval: Interval; + is_current_epoch_over: boolean; + is_current_interval_over: boolean; +} +export interface Interval { + current_epoch_id: number; + current_epoch_start: string; + epoch_length: Duration; + epochs_in_interval: number; + id: number; + total_elapsed_epochs: number; + [k: string]: unknown; +} +export interface MixNodeDelegationResponse { + delegation?: Delegation | null; + mixnode_still_bonded: boolean; +} +export interface PagedDelegatorDelegationsResponse { + delegations: Delegation[]; + start_next_after?: [number, string] | null; +} +export type EpochState = "in_progress" | { + rewarding: { + final_node_id: number; + last_rewarded: number; + }; +} | "reconciling_events" | "advancing_epoch"; +export interface EpochStatus { + being_advanced_by: Addr; + state: EpochState; +} +export interface EstimatedCurrentEpochRewardResponse { + current_stake_value?: Coin | null; + current_stake_value_detailed_amount?: Decimal | null; + detailed_estimation_amount?: Decimal | null; + estimation?: Coin | null; + original_stake?: Coin | null; +} +export interface FamilyByHeadResponse { + family?: Family | null; + head: FamilyHead; +} +export interface FamilyByLabelResponse { + family?: Family | null; + label: string; +} +export interface FamilyMembersByHeadResponse { + head: FamilyHead; + members: string[]; +} +export interface FamilyMembersByLabelResponse { + label: string; + members: string[]; +} +export interface GatewayBondResponse { + gateway?: GatewayBond | null; + identity: string; +} +export interface GatewayBond { + block_height: number; + gateway: Gateway; + owner: Addr; + pledge_amount: Coin; + proxy?: Addr | null; +} +export interface PagedGatewayResponse { + nodes: GatewayBond[]; + per_page: number; + start_next_after?: string | null; +} +export interface LayerDistribution { + layer1: number; + layer2: number; + layer3: number; +} +export interface PagedMixnodeBondsResponse { + nodes: MixNodeBond[]; + per_page: number; + start_next_after?: number | null; +} +export interface PagedMixnodesDetailsResponse { + nodes: MixNodeDetails[]; + per_page: number; + start_next_after?: number | null; +} +export interface PagedMixNodeDelegationsResponse { + delegations: Delegation[]; + start_next_after?: string | null; +} +export interface MixnodeDetailsResponse { + mix_id: number; + mixnode_details?: MixNodeDetails | null; +} +export interface MixnodeRewardingDetailsResponse { + mix_id: number; + rewarding_details?: MixNodeRewarding | null; +} +export interface NumberOfPendingEventsResponse { + epoch_events: number; + interval_events: number; +} +export interface GatewayOwnershipResponse { + address: Addr; + gateway?: GatewayBond | null; +} +export interface MixOwnershipResponse { + address: Addr; + mixnode_details?: MixNodeDetails | null; +} +export interface PendingRewardResponse { + amount_earned?: Coin | null; + amount_earned_detailed?: Decimal | null; + amount_staked?: Coin | null; + mixnode_still_fully_bonded: boolean; +} +export type PendingEpochEventKind = { + delegate: { + amount: Coin; + mix_id: number; + owner: Addr; + proxy?: Addr | null; + }; +} | { + undelegate: { + mix_id: number; + owner: Addr; + proxy?: Addr | null; + }; +} | { + pledge_more: { + amount: Coin; + mix_id: number; + }; +} | { + decrease_pledge: { + decrease_by: Coin; + mix_id: number; + }; +} | { + unbond_mixnode: { + mix_id: number; + }; +} | { + update_active_set_size: { + new_size: number; + }; +}; +export interface PendingEpochEventResponse { + event?: PendingEpochEventData | null; + event_id: number; +} +export interface PendingEpochEventData { + created_at: number; + kind: PendingEpochEventKind; +} +export interface PendingEpochEventsResponse { + events: PendingEpochEvent[]; + seconds_until_executable: number; + start_next_after?: number | null; +} +export interface PendingEpochEvent { + event: PendingEpochEventData; + id: number; +} +export type PendingIntervalEventKind = { + change_mix_cost_params: { + mix_id: number; + new_costs: MixNodeCostParams; + }; +} | { + update_rewarding_params: { + update: IntervalRewardingParamsUpdate; + }; +} | { + update_interval_config: { + epoch_duration_secs: number; + epochs_in_interval: number; + }; +}; +export interface PendingIntervalEventResponse { + event?: PendingIntervalEventData | null; + event_id: number; +} +export interface PendingIntervalEventData { + created_at: number; + kind: PendingIntervalEventKind; +} +export interface PendingIntervalEventsResponse { + events: PendingIntervalEvent[]; + seconds_until_executable: number; + start_next_after?: number | null; +} +export interface PendingIntervalEvent { + event: PendingIntervalEventData; + id: number; +} +export type RewardedSetNodeStatus = "active" | "standby"; +export interface PagedRewardedSetResponse { + nodes: [number, RewardedSetNodeStatus][]; + start_next_after?: number | null; +} +export interface RewardingParams { + active_set_size: number; + interval: IntervalRewardParams; + rewarded_set_size: number; +} +export interface IntervalRewardParams { + active_set_work_factor: Decimal; + epoch_reward_budget: Decimal; + interval_pool_emission: Percent; + reward_pool: Decimal; + stake_saturation_point: Decimal; + staking_supply: Decimal; + staking_supply_scale_factor: Percent; + sybil_resistance: Percent; +} +export type String = string; +export type Uint32 = number; +export interface StakeSaturationResponse { + current_saturation?: Decimal | null; + mix_id: number; + uncapped_saturation?: Decimal | null; +} +export interface ContractState { + owner: Addr; + params: ContractStateParams; + rewarding_denom: string; + rewarding_validator_address: Addr; + vesting_contract_address: Addr; +} +export interface UnbondedMixnodeResponse { + mix_id: number; + unbonded_info?: UnbondedMixnode | null; +} +export interface UnbondedMixnode { + identity_key: string; + owner: Addr; + proxy?: Addr | null; + unbonding_height: number; +} +export interface PagedUnbondedMixnodesResponse { + nodes: [number, UnbondedMixnode][]; + per_page: number; + start_next_after?: number | null; +} diff --git a/sdk/typescript/codegen/contract-clients/src/NameService.client.ts b/sdk/typescript/codegen/contract-clients/src/NameService.client.ts new file mode 100644 index 0000000000..5f5444f0fc --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/NameService.client.ts @@ -0,0 +1,241 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; +import { StdFee } from "@cosmjs/amino"; +import { Uint128, InstantiateMsg, Coin, ExecuteMsg, Address, NymName, MessageSignature, NameDetails, QueryMsg, MigrateMsg, Addr, PagedNamesListResponse, RegisteredName, NamesListResponse, ConfigResponse, ContractVersion, ContractBuildInformation, Uint32 } from "./NameService.types"; +import { GetCw2ContractVersionResponse } from './types'; +export interface NameServiceReadOnlyInterface { + contractAddress: string; + nameId: ({ + nameId + }: { + nameId: number; + }) => Promise; + byOwner: ({ + owner + }: { + owner: string; + }) => Promise; + byName: ({ + name + }: { + name: NymName; + }) => Promise; + byAddress: ({ + address + }: { + address: Address; + }) => Promise; + all: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }) => Promise; + signingNonce: ({ + address + }: { + address: string; + }) => Promise; + config: () => Promise; + getContractVersion: () => Promise; + getCw2ContractVersion: () => Promise; +} +export class NameServiceQueryClient implements NameServiceReadOnlyInterface { + client: CosmWasmClient; + contractAddress: string; + + constructor(client: CosmWasmClient, contractAddress: string) { + this.client = client; + this.contractAddress = contractAddress; + this.nameId = this.nameId.bind(this); + this.byOwner = this.byOwner.bind(this); + this.byName = this.byName.bind(this); + this.byAddress = this.byAddress.bind(this); + this.all = this.all.bind(this); + this.signingNonce = this.signingNonce.bind(this); + this.config = this.config.bind(this); + this.getContractVersion = this.getContractVersion.bind(this); + this.getCw2ContractVersion = this.getCw2ContractVersion.bind(this); + } + + nameId = async ({ + nameId + }: { + nameId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + name_id: { + name_id: nameId + } + }); + }; + byOwner = async ({ + owner + }: { + owner: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + by_owner: { + owner + } + }); + }; + byName = async ({ + name + }: { + name: NymName; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + by_name: { + name + } + }); + }; + byAddress = async ({ + address + }: { + address: Address; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + by_address: { + address + } + }); + }; + all = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + all: { + limit, + start_after: startAfter + } + }); + }; + signingNonce = async ({ + address + }: { + address: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + signing_nonce: { + address + } + }); + }; + config = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + config: {} + }); + }; + getContractVersion = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_contract_version: {} + }); + }; + getCw2ContractVersion = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_cw2_contract_version: {} + }); + }; +} +export interface NameServiceInterface extends NameServiceReadOnlyInterface { + contractAddress: string; + sender: string; + register: ({ + name, + ownerSignature + }: { + name: NameDetails; + ownerSignature: MessageSignature; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + deleteId: ({ + nameId + }: { + nameId: number; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + deleteName: ({ + name + }: { + name: NymName; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateDepositRequired: ({ + depositRequired + }: { + depositRequired: Coin; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; +} +export class NameServiceClient extends NameServiceQueryClient implements NameServiceInterface { + client: SigningCosmWasmClient; + sender: string; + contractAddress: string; + + constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) { + super(client, contractAddress); + this.client = client; + this.sender = sender; + this.contractAddress = contractAddress; + this.register = this.register.bind(this); + this.deleteId = this.deleteId.bind(this); + this.deleteName = this.deleteName.bind(this); + this.updateDepositRequired = this.updateDepositRequired.bind(this); + } + + register = async ({ + name, + ownerSignature + }: { + name: NameDetails; + ownerSignature: MessageSignature; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + register: { + name, + owner_signature: ownerSignature + } + }, fee, memo, _funds); + }; + deleteId = async ({ + nameId + }: { + nameId: number; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + delete_id: { + name_id: nameId + } + }, fee, memo, _funds); + }; + deleteName = async ({ + name + }: { + name: NymName; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + delete_name: { + name + } + }, fee, memo, _funds); + }; + updateDepositRequired = async ({ + depositRequired + }: { + depositRequired: Coin; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_deposit_required: { + deposit_required: depositRequired + } + }, fee, memo, _funds); + }; +} diff --git a/sdk/typescript/codegen/contract-clients/src/NameService.types.ts b/sdk/typescript/codegen/contract-clients/src/NameService.types.ts new file mode 100644 index 0000000000..c9d80b5936 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/NameService.types.ts @@ -0,0 +1,108 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +export type Uint128 = string; +export interface InstantiateMsg { + deposit_required: Coin; +} +export interface Coin { + amount: Uint128; + denom: string; + [k: string]: unknown; +} +export type ExecuteMsg = { + register: { + name: NameDetails; + owner_signature: MessageSignature; + }; +} | { + delete_id: { + name_id: number; + }; +} | { + delete_name: { + name: NymName; + }; +} | { + update_deposit_required: { + deposit_required: Coin; + }; +}; +export type Address = { + nym_address: string; +}; +export type NymName = string; +export type MessageSignature = number[]; +export interface NameDetails { + address: Address; + identity_key: string; + name: NymName; +} +export type QueryMsg = { + name_id: { + name_id: number; + }; +} | { + by_owner: { + owner: string; + }; +} | { + by_name: { + name: NymName; + }; +} | { + by_address: { + address: Address; + }; +} | { + all: { + limit?: number | null; + start_after?: number | null; + }; +} | { + signing_nonce: { + address: string; + }; +} | { + config: {}; +} | { + get_contract_version: {}; +} | { + get_cw2_contract_version: {}; +}; +export interface MigrateMsg {} +export type Addr = string; +export interface PagedNamesListResponse { + names: RegisteredName[]; + per_page: number; + start_next_after?: number | null; +} +export interface RegisteredName { + block_height: number; + deposit: Coin; + id: number; + name: NameDetails; + owner: Addr; +} +export interface NamesListResponse { + names: RegisteredName[]; +} +export interface ConfigResponse { + deposit_required: Coin; +} +export interface ContractVersion { + contract: string; + version: string; +} +export interface ContractBuildInformation { + build_timestamp: string; + build_version: string; + commit_branch: string; + commit_sha: string; + commit_timestamp: string; + rustc_version: string; +} +export type Uint32 = number; \ No newline at end of file diff --git a/sdk/typescript/codegen/contract-clients/src/ServiceProviderDirectory.client.ts b/sdk/typescript/codegen/contract-clients/src/ServiceProviderDirectory.client.ts new file mode 100644 index 0000000000..07f631e545 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/ServiceProviderDirectory.client.ts @@ -0,0 +1,224 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; +import { StdFee } from "@cosmjs/amino"; +import { Uint128, InstantiateMsg, Coin, ExecuteMsg, MessageSignature, NymAddress, ServiceType, ServiceDetails, QueryMsg, MigrateMsg, Addr, PagedServicesListResponse, Service, ServicesListResponse, ConfigResponse, ContractVersion, ContractBuildInformation, Uint32 } from "./ServiceProviderDirectory.types"; +import { GetCw2ContractVersionResponse } from './types'; +export interface ServiceProviderDirectoryReadOnlyInterface { + contractAddress: string; + serviceId: ({ + serviceId + }: { + serviceId: number; + }) => Promise; + byAnnouncer: ({ + announcer + }: { + announcer: string; + }) => Promise; + byNymAddress: ({ + nymAddress + }: { + nymAddress: NymAddress; + }) => Promise; + all: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }) => Promise; + signingNonce: ({ + address + }: { + address: string; + }) => Promise; + config: () => Promise; + getContractVersion: () => Promise; + getCw2ContractVersion: () => Promise; +} +export class ServiceProviderDirectoryQueryClient implements ServiceProviderDirectoryReadOnlyInterface { + client: CosmWasmClient; + contractAddress: string; + + constructor(client: CosmWasmClient, contractAddress: string) { + this.client = client; + this.contractAddress = contractAddress; + this.serviceId = this.serviceId.bind(this); + this.byAnnouncer = this.byAnnouncer.bind(this); + this.byNymAddress = this.byNymAddress.bind(this); + this.all = this.all.bind(this); + this.signingNonce = this.signingNonce.bind(this); + this.config = this.config.bind(this); + this.getContractVersion = this.getContractVersion.bind(this); + this.getCw2ContractVersion = this.getCw2ContractVersion.bind(this); + } + + serviceId = async ({ + serviceId + }: { + serviceId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + service_id: { + service_id: serviceId + } + }); + }; + byAnnouncer = async ({ + announcer + }: { + announcer: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + by_announcer: { + announcer + } + }); + }; + byNymAddress = async ({ + nymAddress + }: { + nymAddress: NymAddress; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + by_nym_address: { + nym_address: nymAddress + } + }); + }; + all = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + all: { + limit, + start_after: startAfter + } + }); + }; + signingNonce = async ({ + address + }: { + address: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + signing_nonce: { + address + } + }); + }; + config = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + config: {} + }); + }; + getContractVersion = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_contract_version: {} + }); + }; + getCw2ContractVersion = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_cw2_contract_version: {} + }); + }; +} +export interface ServiceProviderDirectoryInterface extends ServiceProviderDirectoryReadOnlyInterface { + contractAddress: string; + sender: string; + announce: ({ + ownerSignature, + service + }: { + ownerSignature: MessageSignature; + service: ServiceDetails; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + deleteId: ({ + serviceId + }: { + serviceId: number; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + deleteNymAddress: ({ + nymAddress + }: { + nymAddress: NymAddress; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateDepositRequired: ({ + depositRequired + }: { + depositRequired: Coin; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; +} +export class ServiceProviderDirectoryClient extends ServiceProviderDirectoryQueryClient implements ServiceProviderDirectoryInterface { + client: SigningCosmWasmClient; + sender: string; + contractAddress: string; + + constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) { + super(client, contractAddress); + this.client = client; + this.sender = sender; + this.contractAddress = contractAddress; + this.announce = this.announce.bind(this); + this.deleteId = this.deleteId.bind(this); + this.deleteNymAddress = this.deleteNymAddress.bind(this); + this.updateDepositRequired = this.updateDepositRequired.bind(this); + } + + announce = async ({ + ownerSignature, + service + }: { + ownerSignature: MessageSignature; + service: ServiceDetails; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + announce: { + owner_signature: ownerSignature, + service + } + }, fee, memo, _funds); + }; + deleteId = async ({ + serviceId + }: { + serviceId: number; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + delete_id: { + service_id: serviceId + } + }, fee, memo, _funds); + }; + deleteNymAddress = async ({ + nymAddress + }: { + nymAddress: NymAddress; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + delete_nym_address: { + nym_address: nymAddress + } + }, fee, memo, _funds); + }; + updateDepositRequired = async ({ + depositRequired + }: { + depositRequired: Coin; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_deposit_required: { + deposit_required: depositRequired + } + }, fee, memo, _funds); + }; +} diff --git a/sdk/typescript/codegen/contract-clients/src/ServiceProviderDirectory.types.ts b/sdk/typescript/codegen/contract-clients/src/ServiceProviderDirectory.types.ts new file mode 100644 index 0000000000..9cf727132b --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/ServiceProviderDirectory.types.ts @@ -0,0 +1,104 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +export type Uint128 = string; +export interface InstantiateMsg { + deposit_required: Coin; +} +export interface Coin { + amount: Uint128; + denom: string; + [k: string]: unknown; +} +export type ExecuteMsg = { + announce: { + owner_signature: MessageSignature; + service: ServiceDetails; + }; +} | { + delete_id: { + service_id: number; + }; +} | { + delete_nym_address: { + nym_address: NymAddress; + }; +} | { + update_deposit_required: { + deposit_required: Coin; + }; +}; +export type MessageSignature = number[]; +export type NymAddress = { + address: string; +}; +export type ServiceType = "network_requester"; +export interface ServiceDetails { + identity_key: string; + nym_address: NymAddress; + service_type: ServiceType; +} +export type QueryMsg = { + service_id: { + service_id: number; + }; +} | { + by_announcer: { + announcer: string; + }; +} | { + by_nym_address: { + nym_address: NymAddress; + }; +} | { + all: { + limit?: number | null; + start_after?: number | null; + }; +} | { + signing_nonce: { + address: string; + }; +} | { + config: {}; +} | { + get_contract_version: {}; +} | { + get_cw2_contract_version: {}; +}; +export interface MigrateMsg {} +export type Addr = string; +export interface PagedServicesListResponse { + per_page: number; + services: Service[]; + start_next_after?: number | null; +} +export interface Service { + announcer: Addr; + block_height: number; + deposit: Coin; + service: ServiceDetails; + service_id: number; +} +export interface ServicesListResponse { + services: Service[]; +} +export interface ConfigResponse { + deposit_required: Coin; +} +export interface ContractVersion { + contract: string; + version: string; +} +export interface ContractBuildInformation { + build_timestamp: string; + build_version: string; + commit_branch: string; + commit_sha: string; + commit_timestamp: string; + rustc_version: string; +} +export type Uint32 = number; \ No newline at end of file diff --git a/sdk/typescript/codegen/contract-clients/src/Vesting.client.ts b/sdk/typescript/codegen/contract-clients/src/Vesting.client.ts new file mode 100644 index 0000000000..57e08e327a --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/Vesting.client.ts @@ -0,0 +1,1058 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; +import { StdFee } from "@cosmjs/amino"; +import { InstantiateMsg, ExecuteMsg, FamilyHead, MessageSignature, Uint128, Percent, Decimal, PledgeCap, Coin, MixNodeCostParams, MixNodeConfigUpdate, VestingSpecification, MixNode, Gateway, GatewayConfigUpdate, QueryMsg, Timestamp, Uint64, MigrateMsg, Addr, Account, VestingPeriod, AccountsResponse, BaseVestingAccountInfo, VestingCoinsResponse, AccountVestingCoins, AllDelegationsResponse, VestingDelegation, ContractVersion, ContractBuildInformation, Period, DelegationTimesResponse, NullablePledgeData, PledgeData, OriginalVestingResponse } from "./Vesting.types"; +import { GetCw2ContractVersionResponse } from './types'; +export interface VestingReadOnlyInterface { + contractAddress: string; + getContractVersion: () => Promise; + getCw2ContractVersion: () => Promise; + getAccountsPaged: ({ + limit, + startNextAfter + }: { + limit?: number; + startNextAfter?: string; + }) => Promise; + getAccountsVestingCoinsPaged: ({ + limit, + startNextAfter + }: { + limit?: number; + startNextAfter?: string; + }) => Promise; + lockedCoins: ({ + blockTime, + vestingAccountAddress + }: { + blockTime?: Timestamp; + vestingAccountAddress: string; + }) => Promise; + spendableCoins: ({ + blockTime, + vestingAccountAddress + }: { + blockTime?: Timestamp; + vestingAccountAddress: string; + }) => Promise; + getVestedCoins: ({ + blockTime, + vestingAccountAddress + }: { + blockTime?: Timestamp; + vestingAccountAddress: string; + }) => Promise; + getVestingCoins: ({ + blockTime, + vestingAccountAddress + }: { + blockTime?: Timestamp; + vestingAccountAddress: string; + }) => Promise; + getStartTime: ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }) => Promise; + getEndTime: ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }) => Promise; + getOriginalVesting: ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }) => Promise; + getHistoricalVestingStakingReward: ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }) => Promise; + getSpendableVestedCoins: ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }) => Promise; + getSpendableRewardCoins: ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }) => Promise; + getDelegatedCoins: ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }) => Promise; + getPledgedCoins: ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }) => Promise; + getStakedCoins: ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }) => Promise; + getWithdrawnCoins: ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }) => Promise; + getAccount: ({ + address + }: { + address: string; + }) => Promise; + getMixnode: ({ + address + }: { + address: string; + }) => Promise; + getGateway: ({ + address + }: { + address: string; + }) => Promise; + getCurrentVestingPeriod: ({ + address + }: { + address: string; + }) => Promise; + getDelegation: ({ + address, + blockTimestampSecs, + mixId + }: { + address: string; + blockTimestampSecs: number; + mixId: number; + }) => Promise; + getTotalDelegationAmount: ({ + address, + mixId + }: { + address: string; + mixId: number; + }) => Promise; + getDelegationTimes: ({ + address, + mixId + }: { + address: string; + mixId: number; + }) => Promise; + getAllDelegations: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number[][]; + }) => Promise; +} +export class VestingQueryClient implements VestingReadOnlyInterface { + client: CosmWasmClient; + contractAddress: string; + + constructor(client: CosmWasmClient, contractAddress: string) { + this.client = client; + this.contractAddress = contractAddress; + this.getContractVersion = this.getContractVersion.bind(this); + this.getCw2ContractVersion = this.getCw2ContractVersion.bind(this); + this.getAccountsPaged = this.getAccountsPaged.bind(this); + this.getAccountsVestingCoinsPaged = this.getAccountsVestingCoinsPaged.bind(this); + this.lockedCoins = this.lockedCoins.bind(this); + this.spendableCoins = this.spendableCoins.bind(this); + this.getVestedCoins = this.getVestedCoins.bind(this); + this.getVestingCoins = this.getVestingCoins.bind(this); + this.getStartTime = this.getStartTime.bind(this); + this.getEndTime = this.getEndTime.bind(this); + this.getOriginalVesting = this.getOriginalVesting.bind(this); + this.getHistoricalVestingStakingReward = this.getHistoricalVestingStakingReward.bind(this); + this.getSpendableVestedCoins = this.getSpendableVestedCoins.bind(this); + this.getSpendableRewardCoins = this.getSpendableRewardCoins.bind(this); + this.getDelegatedCoins = this.getDelegatedCoins.bind(this); + this.getPledgedCoins = this.getPledgedCoins.bind(this); + this.getStakedCoins = this.getStakedCoins.bind(this); + this.getWithdrawnCoins = this.getWithdrawnCoins.bind(this); + this.getAccount = this.getAccount.bind(this); + this.getMixnode = this.getMixnode.bind(this); + this.getGateway = this.getGateway.bind(this); + this.getCurrentVestingPeriod = this.getCurrentVestingPeriod.bind(this); + this.getDelegation = this.getDelegation.bind(this); + this.getTotalDelegationAmount = this.getTotalDelegationAmount.bind(this); + this.getDelegationTimes = this.getDelegationTimes.bind(this); + this.getAllDelegations = this.getAllDelegations.bind(this); + } + + getContractVersion = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_contract_version: {} + }); + }; + getCw2ContractVersion = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_cw2_contract_version: {} + }); + }; + getAccountsPaged = async ({ + limit, + startNextAfter + }: { + limit?: number; + startNextAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_accounts_paged: { + limit, + start_next_after: startNextAfter + } + }); + }; + getAccountsVestingCoinsPaged = async ({ + limit, + startNextAfter + }: { + limit?: number; + startNextAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_accounts_vesting_coins_paged: { + limit, + start_next_after: startNextAfter + } + }); + }; + lockedCoins = async ({ + blockTime, + vestingAccountAddress + }: { + blockTime?: Timestamp; + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + locked_coins: { + block_time: blockTime, + vesting_account_address: vestingAccountAddress + } + }); + }; + spendableCoins = async ({ + blockTime, + vestingAccountAddress + }: { + blockTime?: Timestamp; + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + spendable_coins: { + block_time: blockTime, + vesting_account_address: vestingAccountAddress + } + }); + }; + getVestedCoins = async ({ + blockTime, + vestingAccountAddress + }: { + blockTime?: Timestamp; + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_vested_coins: { + block_time: blockTime, + vesting_account_address: vestingAccountAddress + } + }); + }; + getVestingCoins = async ({ + blockTime, + vestingAccountAddress + }: { + blockTime?: Timestamp; + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_vesting_coins: { + block_time: blockTime, + vesting_account_address: vestingAccountAddress + } + }); + }; + getStartTime = async ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_start_time: { + vesting_account_address: vestingAccountAddress + } + }); + }; + getEndTime = async ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_end_time: { + vesting_account_address: vestingAccountAddress + } + }); + }; + getOriginalVesting = async ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_original_vesting: { + vesting_account_address: vestingAccountAddress + } + }); + }; + getHistoricalVestingStakingReward = async ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_historical_vesting_staking_reward: { + vesting_account_address: vestingAccountAddress + } + }); + }; + getSpendableVestedCoins = async ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_spendable_vested_coins: { + vesting_account_address: vestingAccountAddress + } + }); + }; + getSpendableRewardCoins = async ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_spendable_reward_coins: { + vesting_account_address: vestingAccountAddress + } + }); + }; + getDelegatedCoins = async ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_delegated_coins: { + vesting_account_address: vestingAccountAddress + } + }); + }; + getPledgedCoins = async ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_pledged_coins: { + vesting_account_address: vestingAccountAddress + } + }); + }; + getStakedCoins = async ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_staked_coins: { + vesting_account_address: vestingAccountAddress + } + }); + }; + getWithdrawnCoins = async ({ + vestingAccountAddress + }: { + vestingAccountAddress: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_withdrawn_coins: { + vesting_account_address: vestingAccountAddress + } + }); + }; + getAccount = async ({ + address + }: { + address: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_account: { + address + } + }); + }; + getMixnode = async ({ + address + }: { + address: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_mixnode: { + address + } + }); + }; + getGateway = async ({ + address + }: { + address: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_gateway: { + address + } + }); + }; + getCurrentVestingPeriod = async ({ + address + }: { + address: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_current_vesting_period: { + address + } + }); + }; + getDelegation = async ({ + address, + blockTimestampSecs, + mixId + }: { + address: string; + blockTimestampSecs: number; + mixId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_delegation: { + address, + block_timestamp_secs: blockTimestampSecs, + mix_id: mixId + } + }); + }; + getTotalDelegationAmount = async ({ + address, + mixId + }: { + address: string; + mixId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_total_delegation_amount: { + address, + mix_id: mixId + } + }); + }; + getDelegationTimes = async ({ + address, + mixId + }: { + address: string; + mixId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_delegation_times: { + address, + mix_id: mixId + } + }); + }; + getAllDelegations = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: number[][]; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_all_delegations: { + limit, + start_after: startAfter + } + }); + }; +} +export interface VestingInterface extends VestingReadOnlyInterface { + contractAddress: string; + sender: string; + createFamily: ({ + label + }: { + label: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + joinFamily: ({ + familyHead, + joinPermit + }: { + familyHead: FamilyHead; + joinPermit: MessageSignature; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + leaveFamily: ({ + familyHead + }: { + familyHead: FamilyHead; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + kickFamilyMember: ({ + member + }: { + member: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + trackReward: ({ + address, + amount + }: { + address: string; + amount: Coin; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + claimOperatorReward: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + claimDelegatorReward: ({ + mixId + }: { + mixId: number; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateMixnodeCostParams: ({ + newCosts + }: { + newCosts: MixNodeCostParams; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateMixnodeConfig: ({ + newConfig + }: { + newConfig: MixNodeConfigUpdate; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateMixnetAddress: ({ + address + }: { + address: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + delegateToMixnode: ({ + amount, + mixId, + onBehalfOf + }: { + amount: Coin; + mixId: number; + onBehalfOf?: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + undelegateFromMixnode: ({ + mixId, + onBehalfOf + }: { + mixId: number; + onBehalfOf?: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + createAccount: ({ + cap, + ownerAddress, + stakingAddress, + vestingSpec + }: { + cap?: PledgeCap; + ownerAddress: string; + stakingAddress?: string; + vestingSpec?: VestingSpecification; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + withdrawVestedCoins: ({ + amount + }: { + amount: Coin; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + trackUndelegation: ({ + amount, + mixId, + owner + }: { + amount: Coin; + mixId: number; + owner: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + bondMixnode: ({ + amount, + costParams, + mixNode, + ownerSignature + }: { + amount: Coin; + costParams: MixNodeCostParams; + mixNode: MixNode; + ownerSignature: MessageSignature; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + pledgeMore: ({ + amount + }: { + amount: Coin; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + decreasePledge: ({ + amount + }: { + amount: Coin; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + unbondMixnode: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + trackUnbondMixnode: ({ + amount, + owner + }: { + amount: Coin; + owner: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + trackDecreasePledge: ({ + amount, + owner + }: { + amount: Coin; + owner: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + bondGateway: ({ + amount, + gateway, + ownerSignature + }: { + amount: Coin; + gateway: Gateway; + ownerSignature: MessageSignature; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + unbondGateway: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + trackUnbondGateway: ({ + amount, + owner + }: { + amount: Coin; + owner: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateGatewayConfig: ({ + newConfig + }: { + newConfig: GatewayConfigUpdate; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + transferOwnership: ({ + toAddress + }: { + toAddress: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateStakingAddress: ({ + toAddress + }: { + toAddress?: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateLockedPledgeCap: ({ + address, + cap + }: { + address: string; + cap: PledgeCap; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; +} +export class VestingClient extends VestingQueryClient implements VestingInterface { + client: SigningCosmWasmClient; + sender: string; + contractAddress: string; + + constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) { + super(client, contractAddress); + this.client = client; + this.sender = sender; + this.contractAddress = contractAddress; + this.createFamily = this.createFamily.bind(this); + this.joinFamily = this.joinFamily.bind(this); + this.leaveFamily = this.leaveFamily.bind(this); + this.kickFamilyMember = this.kickFamilyMember.bind(this); + this.trackReward = this.trackReward.bind(this); + this.claimOperatorReward = this.claimOperatorReward.bind(this); + this.claimDelegatorReward = this.claimDelegatorReward.bind(this); + this.updateMixnodeCostParams = this.updateMixnodeCostParams.bind(this); + this.updateMixnodeConfig = this.updateMixnodeConfig.bind(this); + this.updateMixnetAddress = this.updateMixnetAddress.bind(this); + this.delegateToMixnode = this.delegateToMixnode.bind(this); + this.undelegateFromMixnode = this.undelegateFromMixnode.bind(this); + this.createAccount = this.createAccount.bind(this); + this.withdrawVestedCoins = this.withdrawVestedCoins.bind(this); + this.trackUndelegation = this.trackUndelegation.bind(this); + this.bondMixnode = this.bondMixnode.bind(this); + this.pledgeMore = this.pledgeMore.bind(this); + this.decreasePledge = this.decreasePledge.bind(this); + this.unbondMixnode = this.unbondMixnode.bind(this); + this.trackUnbondMixnode = this.trackUnbondMixnode.bind(this); + this.trackDecreasePledge = this.trackDecreasePledge.bind(this); + this.bondGateway = this.bondGateway.bind(this); + this.unbondGateway = this.unbondGateway.bind(this); + this.trackUnbondGateway = this.trackUnbondGateway.bind(this); + this.updateGatewayConfig = this.updateGatewayConfig.bind(this); + this.transferOwnership = this.transferOwnership.bind(this); + this.updateStakingAddress = this.updateStakingAddress.bind(this); + this.updateLockedPledgeCap = this.updateLockedPledgeCap.bind(this); + } + + createFamily = async ({ + label + }: { + label: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + create_family: { + label + } + }, fee, memo, _funds); + }; + joinFamily = async ({ + familyHead, + joinPermit + }: { + familyHead: FamilyHead; + joinPermit: MessageSignature; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + join_family: { + family_head: familyHead, + join_permit: joinPermit + } + }, fee, memo, _funds); + }; + leaveFamily = async ({ + familyHead + }: { + familyHead: FamilyHead; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + leave_family: { + family_head: familyHead + } + }, fee, memo, _funds); + }; + kickFamilyMember = async ({ + member + }: { + member: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + kick_family_member: { + member + } + }, fee, memo, _funds); + }; + trackReward = async ({ + address, + amount + }: { + address: string; + amount: Coin; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + track_reward: { + address, + amount + } + }, fee, memo, _funds); + }; + claimOperatorReward = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + claim_operator_reward: {} + }, fee, memo, _funds); + }; + claimDelegatorReward = async ({ + mixId + }: { + mixId: number; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + claim_delegator_reward: { + mix_id: mixId + } + }, fee, memo, _funds); + }; + updateMixnodeCostParams = async ({ + newCosts + }: { + newCosts: MixNodeCostParams; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_mixnode_cost_params: { + new_costs: newCosts + } + }, fee, memo, _funds); + }; + updateMixnodeConfig = async ({ + newConfig + }: { + newConfig: MixNodeConfigUpdate; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_mixnode_config: { + new_config: newConfig + } + }, fee, memo, _funds); + }; + updateMixnetAddress = async ({ + address + }: { + address: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_mixnet_address: { + address + } + }, fee, memo, _funds); + }; + delegateToMixnode = async ({ + amount, + mixId, + onBehalfOf + }: { + amount: Coin; + mixId: number; + onBehalfOf?: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + delegate_to_mixnode: { + amount, + mix_id: mixId, + on_behalf_of: onBehalfOf + } + }, fee, memo, _funds); + }; + undelegateFromMixnode = async ({ + mixId, + onBehalfOf + }: { + mixId: number; + onBehalfOf?: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + undelegate_from_mixnode: { + mix_id: mixId, + on_behalf_of: onBehalfOf + } + }, fee, memo, _funds); + }; + createAccount = async ({ + cap, + ownerAddress, + stakingAddress, + vestingSpec + }: { + cap?: PledgeCap; + ownerAddress: string; + stakingAddress?: string; + vestingSpec?: VestingSpecification; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + create_account: { + cap, + owner_address: ownerAddress, + staking_address: stakingAddress, + vesting_spec: vestingSpec + } + }, fee, memo, _funds); + }; + withdrawVestedCoins = async ({ + amount + }: { + amount: Coin; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + withdraw_vested_coins: { + amount + } + }, fee, memo, _funds); + }; + trackUndelegation = async ({ + amount, + mixId, + owner + }: { + amount: Coin; + mixId: number; + owner: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + track_undelegation: { + amount, + mix_id: mixId, + owner + } + }, fee, memo, _funds); + }; + bondMixnode = async ({ + amount, + costParams, + mixNode, + ownerSignature + }: { + amount: Coin; + costParams: MixNodeCostParams; + mixNode: MixNode; + ownerSignature: MessageSignature; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + bond_mixnode: { + amount, + cost_params: costParams, + mix_node: mixNode, + owner_signature: ownerSignature + } + }, fee, memo, _funds); + }; + pledgeMore = async ({ + amount + }: { + amount: Coin; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + pledge_more: { + amount + } + }, fee, memo, _funds); + }; + decreasePledge = async ({ + amount + }: { + amount: Coin; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + decrease_pledge: { + amount + } + }, fee, memo, _funds); + }; + unbondMixnode = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + unbond_mixnode: {} + }, fee, memo, _funds); + }; + trackUnbondMixnode = async ({ + amount, + owner + }: { + amount: Coin; + owner: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + track_unbond_mixnode: { + amount, + owner + } + }, fee, memo, _funds); + }; + trackDecreasePledge = async ({ + amount, + owner + }: { + amount: Coin; + owner: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + track_decrease_pledge: { + amount, + owner + } + }, fee, memo, _funds); + }; + bondGateway = async ({ + amount, + gateway, + ownerSignature + }: { + amount: Coin; + gateway: Gateway; + ownerSignature: MessageSignature; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + bond_gateway: { + amount, + gateway, + owner_signature: ownerSignature + } + }, fee, memo, _funds); + }; + unbondGateway = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + unbond_gateway: {} + }, fee, memo, _funds); + }; + trackUnbondGateway = async ({ + amount, + owner + }: { + amount: Coin; + owner: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + track_unbond_gateway: { + amount, + owner + } + }, fee, memo, _funds); + }; + updateGatewayConfig = async ({ + newConfig + }: { + newConfig: GatewayConfigUpdate; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_gateway_config: { + new_config: newConfig + } + }, fee, memo, _funds); + }; + transferOwnership = async ({ + toAddress + }: { + toAddress: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + transfer_ownership: { + to_address: toAddress + } + }, fee, memo, _funds); + }; + updateStakingAddress = async ({ + toAddress + }: { + toAddress?: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_staking_address: { + to_address: toAddress + } + }, fee, memo, _funds); + }; + updateLockedPledgeCap = async ({ + address, + cap + }: { + address: string; + cap: PledgeCap; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_locked_pledge_cap: { + address, + cap + } + }, fee, memo, _funds); + }; +} diff --git a/sdk/typescript/codegen/contract-clients/src/Vesting.types.ts b/sdk/typescript/codegen/contract-clients/src/Vesting.types.ts new file mode 100644 index 0000000000..a07a32a242 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/Vesting.types.ts @@ -0,0 +1,379 @@ +/** +* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run the @cosmwasm/ts-codegen generate command to regenerate this file. +*/ + +export interface InstantiateMsg { + mix_denom: string; + mixnet_contract_address: string; +} +export type ExecuteMsg = { + create_family: { + label: string; + }; +} | { + join_family: { + family_head: FamilyHead; + join_permit: MessageSignature; + }; +} | { + leave_family: { + family_head: FamilyHead; + }; +} | { + kick_family_member: { + member: string; + }; +} | { + track_reward: { + address: string; + amount: Coin; + }; +} | { + claim_operator_reward: {}; +} | { + claim_delegator_reward: { + mix_id: number; + }; +} | { + update_mixnode_cost_params: { + new_costs: MixNodeCostParams; + }; +} | { + update_mixnode_config: { + new_config: MixNodeConfigUpdate; + }; +} | { + update_mixnet_address: { + address: string; + }; +} | { + delegate_to_mixnode: { + amount: Coin; + mix_id: number; + on_behalf_of?: string | null; + }; +} | { + undelegate_from_mixnode: { + mix_id: number; + on_behalf_of?: string | null; + }; +} | { + create_account: { + cap?: PledgeCap | null; + owner_address: string; + staking_address?: string | null; + vesting_spec?: VestingSpecification | null; + }; +} | { + withdraw_vested_coins: { + amount: Coin; + }; +} | { + track_undelegation: { + amount: Coin; + mix_id: number; + owner: string; + }; +} | { + bond_mixnode: { + amount: Coin; + cost_params: MixNodeCostParams; + mix_node: MixNode; + owner_signature: MessageSignature; + }; +} | { + pledge_more: { + amount: Coin; + }; +} | { + decrease_pledge: { + amount: Coin; + }; +} | { + unbond_mixnode: {}; +} | { + track_unbond_mixnode: { + amount: Coin; + owner: string; + }; +} | { + track_decrease_pledge: { + amount: Coin; + owner: string; + }; +} | { + bond_gateway: { + amount: Coin; + gateway: Gateway; + owner_signature: MessageSignature; + }; +} | { + unbond_gateway: {}; +} | { + track_unbond_gateway: { + amount: Coin; + owner: string; + }; +} | { + update_gateway_config: { + new_config: GatewayConfigUpdate; + }; +} | { + transfer_ownership: { + to_address: string; + }; +} | { + update_staking_address: { + to_address?: string | null; + }; +} | { + update_locked_pledge_cap: { + address: string; + cap: PledgeCap; + }; +}; +export type FamilyHead = string; +export type MessageSignature = number[]; +export type Uint128 = string; +export type Percent = Decimal; +export type Decimal = string; +export type PledgeCap = { + percent: Percent; +} | { + absolute: Uint128; +}; +export interface Coin { + amount: Uint128; + denom: string; + [k: string]: unknown; +} +export interface MixNodeCostParams { + interval_operating_cost: Coin; + profit_margin_percent: Percent; +} +export interface MixNodeConfigUpdate { + host: string; + http_api_port: number; + mix_port: number; + verloc_port: number; + version: string; +} +export interface VestingSpecification { + num_periods?: number | null; + period_seconds?: number | null; + start_time?: number | null; +} +export interface MixNode { + host: string; + http_api_port: number; + identity_key: string; + mix_port: number; + sphinx_key: string; + verloc_port: number; + version: string; +} +export interface Gateway { + clients_port: number; + host: string; + identity_key: string; + location: string; + mix_port: number; + sphinx_key: string; + version: string; +} +export interface GatewayConfigUpdate { + clients_port: number; + host: string; + location: string; + mix_port: number; + version: string; +} +export type QueryMsg = { + get_contract_version: {}; +} | { + get_cw2_contract_version: {}; +} | { + get_accounts_paged: { + limit?: number | null; + start_next_after?: string | null; + }; +} | { + get_accounts_vesting_coins_paged: { + limit?: number | null; + start_next_after?: string | null; + }; +} | { + locked_coins: { + block_time?: Timestamp | null; + vesting_account_address: string; + }; +} | { + spendable_coins: { + block_time?: Timestamp | null; + vesting_account_address: string; + }; +} | { + get_vested_coins: { + block_time?: Timestamp | null; + vesting_account_address: string; + }; +} | { + get_vesting_coins: { + block_time?: Timestamp | null; + vesting_account_address: string; + }; +} | { + get_start_time: { + vesting_account_address: string; + }; +} | { + get_end_time: { + vesting_account_address: string; + }; +} | { + get_original_vesting: { + vesting_account_address: string; + }; +} | { + get_historical_vesting_staking_reward: { + vesting_account_address: string; + }; +} | { + get_spendable_vested_coins: { + vesting_account_address: string; + }; +} | { + get_spendable_reward_coins: { + vesting_account_address: string; + }; +} | { + get_delegated_coins: { + vesting_account_address: string; + }; +} | { + get_pledged_coins: { + vesting_account_address: string; + }; +} | { + get_staked_coins: { + vesting_account_address: string; + }; +} | { + get_withdrawn_coins: { + vesting_account_address: string; + }; +} | { + get_account: { + address: string; + }; +} | { + get_mixnode: { + address: string; + }; +} | { + get_gateway: { + address: string; + }; +} | { + get_current_vesting_period: { + address: string; + }; +} | { + get_delegation: { + address: string; + block_timestamp_secs: number; + mix_id: number; + }; +} | { + get_total_delegation_amount: { + address: string; + mix_id: number; + }; +} | { + get_delegation_times: { + address: string; + mix_id: number; + }; +} | { + get_all_delegations: { + limit?: number | null; + start_after?: [number, number, number] | null; + }; +}; +export type Timestamp = Uint64; +export type Uint64 = string; +export interface MigrateMsg {} +export type Addr = string; +export interface Account { + coin: Coin; + owner_address: Addr; + periods: VestingPeriod[]; + pledge_cap?: PledgeCap | null; + staking_address?: Addr | null; + start_time: Timestamp; + storage_key: number; +} +export interface VestingPeriod { + period_seconds: number; + start_time: number; +} +export interface AccountsResponse { + accounts: BaseVestingAccountInfo[]; + start_next_after?: Addr | null; +} +export interface BaseVestingAccountInfo { + account_id: number; + owner: Addr; +} +export interface VestingCoinsResponse { + accounts: AccountVestingCoins[]; + start_next_after?: Addr | null; +} +export interface AccountVestingCoins { + account_id: number; + owner: Addr; + still_vesting: Coin; +} +export interface AllDelegationsResponse { + delegations: VestingDelegation[]; + start_next_after?: [number, number, number] | null; +} +export interface VestingDelegation { + account_id: number; + amount: Uint128; + block_timestamp: number; + mix_id: number; +} +export interface ContractVersion { + contract: string; + version: string; +} +export interface ContractBuildInformation { + build_timestamp: string; + build_version: string; + commit_branch: string; + commit_sha: string; + commit_timestamp: string; + rustc_version: string; +} +export type Period = "before" | { + in: number; +} | "after"; +export interface DelegationTimesResponse { + account_id: number; + delegation_timestamps: number[]; + mix_id: number; + owner: Addr; +} +export type NullablePledgeData = PledgeData | null; +export interface PledgeData { + amount: Coin; + block_time: Timestamp; +} +export interface OriginalVestingResponse { + amount: Coin; + number_of_periods: number; + period_duration: number; +} \ No newline at end of file diff --git a/sdk/typescript/codegen/contract-clients/src/index.ts b/sdk/typescript/codegen/contract-clients/src/index.ts new file mode 100644 index 0000000000..530b718908 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/index.ts @@ -0,0 +1,35 @@ +/** + * This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run the @cosmwasm/ts-codegen generate command to regenerate this file. + */ + +import * as _0 from './CoconutBandwidth.types'; +import * as _1 from './CoconutBandwidth.client'; +import * as _2 from './CoconutDkg.types'; +import * as _3 from './CoconutDkg.client'; +import * as _4 from './Mixnet.types'; +import * as _5 from './Mixnet.client'; +import * as _6 from './Cw3FlexMultisig.types'; +import * as _7 from './Cw3FlexMultisig.client'; +import * as _8 from './Cw4Group.types'; +import * as _9 from './Cw4Group.client'; +import * as _10 from './NameService.types'; +import * as _11 from './NameService.client'; +import * as _12 from './ServiceProviderDirectory.types'; +import * as _13 from './ServiceProviderDirectory.client'; +import * as _14 from './Vesting.types'; +import * as _15 from './Vesting.client'; +export * from './types'; + +/** @namespace */ +export namespace contracts { + export const CoconutBandwidth = { ..._0, ..._1 }; + export const CoconutDkg = { ..._2, ..._3 }; + export const Mixnet = { ..._4, ..._5 }; + export const Cw3FlexMultisig = { ..._6, ..._7 }; + export const Cw4Group = { ..._8, ..._9 }; + export const NameService = { ..._10, ..._11 }; + export const ServiceProviderDirectory = { ..._12, ..._13 }; + export const Vesting = { ..._14, ..._15 }; +} diff --git a/sdk/typescript/codegen/contract-clients/src/types.ts b/sdk/typescript/codegen/contract-clients/src/types.ts new file mode 100644 index 0000000000..aa28f581b1 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/src/types.ts @@ -0,0 +1,4 @@ +export interface GetCw2ContractVersionResponse { + contract: String, + version: String, +} diff --git a/sdk/typescript/codegen/contract-clients/tsconfig.json b/sdk/typescript/codegen/contract-clients/tsconfig.json new file mode 100644 index 0000000000..c130f483b6 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/tsconfig.json @@ -0,0 +1,41 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "lib": [ + "es2021", + "dom", + "dom.iterable", + "esnext", + ], + "outDir": "./dist/", + "module": "esnext", + "target": "esnext", + "allowJs": false, + "strict": true, + "moduleResolution": "node", + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "declaration": true, + "baseUrl": "." + }, + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "jest.config.js", + "webpack.config.js", + "webpack.prod.js", + "webpack.common.js", + "node_modules", + "**/node_modules", + "dist", + "**/dist", + "scripts", + "jest", + "__tests__", + "**/__tests__", + "__jest__", + "**/__jest__", + "config/*", + ] +} diff --git a/sdk/typescript/codegen/contract-clients/typedoc.json b/sdk/typescript/codegen/contract-clients/typedoc.json new file mode 100644 index 0000000000..fee2209163 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/typedoc.json @@ -0,0 +1,31 @@ +{ + "sort": ["kind"], + "entryPoints": ["./src/*.ts"], + "out": "./docs", + "kindSortOrder": [ + "Function", + "Interface", + "TypeAlias", + "Reference", + "Project", + "Module", + "Namespace", + "Enum", + "EnumMember", + "Class", + "Constructor", + "Property", + "Variable", + "Accessor", + "Method", + "ObjectLiteral", + "Parameter", + "TypeParameter", + "TypeLiteral", + "CallSignature", + "ConstructorSignature", + "IndexSignature", + "GetSignature", + "SetSignature" + ] +} diff --git a/sdk/typescript/docs/.gitignore b/sdk/typescript/docs/.gitignore new file mode 100644 index 0000000000..1fcb1529f8 --- /dev/null +++ b/sdk/typescript/docs/.gitignore @@ -0,0 +1 @@ +out diff --git a/sdk/typescript/docs/README.md b/sdk/typescript/docs/README.md new file mode 100644 index 0000000000..2a9c9f4fff --- /dev/null +++ b/sdk/typescript/docs/README.md @@ -0,0 +1,26 @@ +# Nym Typescript SDK Documentation + +This directory contains the interactive documentation for the Typescript SDK. + +If you find any issues with this documentation, please open an issue on https://github.com/nymtech/nym/issues/new/choose. + +## Local development + +``` +npm i +npm run dev +``` + +Open http://localhost:3000 to browse the output that will hot-reload when you make changes. + +## Build + +``` +npm run build +``` + +The static output will be in `./out`; + +## Template details + +This documentation was made with [Nextra](https://nextra.site) using the template from here https://github.com/shuding/nextra-docs-template. diff --git a/sdk/typescript/docs/components/wallet.tsx b/sdk/typescript/docs/components/wallet.tsx new file mode 100644 index 0000000000..666b7a3173 --- /dev/null +++ b/sdk/typescript/docs/components/wallet.tsx @@ -0,0 +1,27 @@ +import React, { FC } from 'react'; + +import { ChainProvider, useChainWallet } from '@cosmos-kit/react'; +import { chains, assets } from 'chain-registry'; +import { wallets } from '@cosmos-kit/keplr'; + +// Import this in your top-level route/layout +import '@interchain-ui/react/styles'; + +const WalletInner: FC = () => { + const chainContext = useChainWallet('nyx', 'keplr'); + + return
{JSON.stringify(chainContext, null, 2)}
; +}; + +export const Wallet: FC = () => ( + // TODO + + +
This is a wallet
+ +
+); diff --git a/sdk/typescript/docs/next-env.d.ts b/sdk/typescript/docs/next-env.d.ts new file mode 100644 index 0000000000..4f11a03dc6 --- /dev/null +++ b/sdk/typescript/docs/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/sdk/typescript/docs/next.config.js b/sdk/typescript/docs/next.config.js new file mode 100644 index 0000000000..f4e7f0aac9 --- /dev/null +++ b/sdk/typescript/docs/next.config.js @@ -0,0 +1,21 @@ +const withNextra = require('nextra')({ + theme: 'nextra-theme-docs', + themeConfig: './theme.config.tsx', +}); + +console.dir(withNextra(), { depth: 30 }); +console.dir(withNextra().rewrites, { depth: 30 }); + +const config = { + ...withNextra(), + output: 'export', + rewrites: undefined, + images: { + unoptimized: true, + }, + basePath: process.env.NODE_ENV === 'development' ? undefined : '/docs/sdk/typescript', // this makes the SDK docs appear at https://nymtech.net/docs/sdk/typescript +}; + +// config.images.unoptimized = true; + +module.exports = config; diff --git a/sdk/typescript/docs/package-lock.json b/sdk/typescript/docs/package-lock.json new file mode 100644 index 0000000000..fc1d744b25 --- /dev/null +++ b/sdk/typescript/docs/package-lock.json @@ -0,0 +1,7113 @@ +{ + "name": "nym-sdk-docs", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "nym-sdk-docs", + "version": "0.0.1", + "dependencies": { + "@cosmjs/amino": "^0.31.0", + "@cosmjs/cosmwasm-stargate": "^0.31.0", + "@cosmos-kit/keplr": "^2.1.0", + "@cosmos-kit/react": "^2.1.1", + "@interchain-ui/react": "^1.3.3", + "chain-registry": "^1.18.0", + "next": "^13.0.6", + "nextra": "latest", + "nextra-theme-docs": "latest", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/node": "18.11.10", + "typescript": "^4.9.3" + } + }, + "node_modules/@babel/runtime": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", + "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@braintree/sanitize-url": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz", + "integrity": "sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg==" + }, + "node_modules/@chain-registry/keplr": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@chain-registry/keplr/-/keplr-1.8.0.tgz", + "integrity": "sha512-P1IyZihR/rZUBgFZm5DGs4LAVpMSJ7QfQ5YV1ofpMNeB0iXEEGC4BuuT8NonwgAyWGOw9/c8Z/cNN8f9m5nFkQ==", + "dependencies": { + "@babel/runtime": "^7.19.4", + "@chain-registry/types": "^0.13.1", + "@keplr-wallet/cosmos": "0.11.16", + "@keplr-wallet/crypto": "0.11.16", + "semver": "^7.3.8" + } + }, + "node_modules/@chain-registry/keplr/node_modules/@keplr-wallet/common": { + "version": "0.11.16", + "resolved": "https://registry.npmjs.org/@keplr-wallet/common/-/common-0.11.16.tgz", + "integrity": "sha512-RTbfe8LkPzQQqYntx53dZTuDUgx+W6KRY4g3fIv1c59DS/bp9ZqjYfUDmj3yH0GQk822zqJJwCtjk+qsgvyebg==", + "dependencies": { + "@keplr-wallet/crypto": "0.11.16", + "buffer": "^6.0.3", + "delay": "^4.4.0" + } + }, + "node_modules/@chain-registry/keplr/node_modules/@keplr-wallet/cosmos": { + "version": "0.11.16", + "resolved": "https://registry.npmjs.org/@keplr-wallet/cosmos/-/cosmos-0.11.16.tgz", + "integrity": "sha512-Rgch9zw+GKQ2wAKw6I5+J8AAlKHs4MhnkGFfTuqy0e453Ig0+KCHvs+IgMURM9j6E7K0OPQVc4vCvWnQLs6Zbw==", + "dependencies": { + "@ethersproject/address": "^5.6.0", + "@keplr-wallet/common": "0.11.16", + "@keplr-wallet/crypto": "0.11.16", + "@keplr-wallet/proto-types": "0.11.16", + "@keplr-wallet/types": "0.11.16", + "@keplr-wallet/unit": "0.11.16", + "axios": "^0.27.2", + "bech32": "^1.1.4", + "buffer": "^6.0.3", + "long": "^4.0.0", + "protobufjs": "^6.11.2" + } + }, + "node_modules/@chain-registry/keplr/node_modules/@keplr-wallet/crypto": { + "version": "0.11.16", + "resolved": "https://registry.npmjs.org/@keplr-wallet/crypto/-/crypto-0.11.16.tgz", + "integrity": "sha512-th3t05Aq+uQLbhhiqIHbevY3pA4dBKr+vKcUpfdshcc78fI1eGpmzGcQKxlvbectBn4UwamTEANssyplXOGQqg==", + "dependencies": { + "@ethersproject/keccak256": "^5.5.0", + "bip32": "^2.0.6", + "bip39": "^3.0.3", + "bs58check": "^2.1.2", + "buffer": "^6.0.3", + "crypto-js": "^4.0.0", + "elliptic": "^6.5.3", + "sha.js": "^2.4.11" + } + }, + "node_modules/@chain-registry/keplr/node_modules/@keplr-wallet/proto-types": { + "version": "0.11.16", + "resolved": "https://registry.npmjs.org/@keplr-wallet/proto-types/-/proto-types-0.11.16.tgz", + "integrity": "sha512-0tX7AN1bmlZdpUwqgjQU6MI+p+qBBaWUxHvOrNYtvX0FShw9RihasWdrV6biciQewVd54fChVIGmYKhCLtwPsg==", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "^6.11.2" + } + }, + "node_modules/@chain-registry/keplr/node_modules/@keplr-wallet/types": { + "version": "0.11.16", + "resolved": "https://registry.npmjs.org/@keplr-wallet/types/-/types-0.11.16.tgz", + "integrity": "sha512-jkBWj6bcw6BZqPavLms3EcaK6YG4suoTPA9PuO6+eFjj7TomUrzzYdhXyc7Mm0K/KVEz5CjPxjmx7LsPuWYKgg==", + "dependencies": { + "axios": "^0.27.2", + "long": "^4.0.0", + "secretjs": "0.17.7" + } + }, + "node_modules/@chain-registry/keplr/node_modules/@keplr-wallet/unit": { + "version": "0.11.16", + "resolved": "https://registry.npmjs.org/@keplr-wallet/unit/-/unit-0.11.16.tgz", + "integrity": "sha512-RRVE3oLZq84P4CQONHXDRX+jdqsP9Zar0V9ROAkG4qzitG2glNY/KCVd9SeSOatbGOb/4X88/4pH273TkjtlRA==", + "dependencies": { + "@keplr-wallet/types": "0.11.16", + "big-integer": "^1.6.48", + "utility-types": "^3.10.0" + } + }, + "node_modules/@chain-registry/keplr/node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/@chain-registry/types": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@chain-registry/types/-/types-0.13.1.tgz", + "integrity": "sha512-NF4x7pqkQJ/zSQLoT28sYlBdzWUyCTFvWgVE9hJ2jkirX+It9VUHP5j1wtTq+vxQ74SZk2V8vRBo2uuoEYBB1A==", + "dependencies": { + "@babel/runtime": "^7.19.4" + } + }, + "node_modules/@confio/ics23": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@confio/ics23/-/ics23-0.6.8.tgz", + "integrity": "sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w==", + "dependencies": { + "@noble/hashes": "^1.0.0", + "protobufjs": "^6.8.8" + } + }, + "node_modules/@cosmjs/amino": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.31.0.tgz", + "integrity": "sha512-xJ5CCEK7H79FTpOuEmlpSzVI+ZeYESTVvO3wHDgbnceIyAne3C68SvyaKqLUR4uJB0Z4q4+DZHbqW6itUiv4lA==", + "dependencies": { + "@cosmjs/crypto": "^0.31.0", + "@cosmjs/encoding": "^0.31.0", + "@cosmjs/math": "^0.31.0", + "@cosmjs/utils": "^0.31.0" + } + }, + "node_modules/@cosmjs/cosmwasm-stargate": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.31.0.tgz", + "integrity": "sha512-l6aX++3LhaAGZO46qIgrrNF40lYhOrdPfl35Z32ks6Wf3mwgbQEZwaxnoGzwUePY7/yaIiEFJ1JO6MlVPZVuag==", + "dependencies": { + "@cosmjs/amino": "^0.31.0", + "@cosmjs/crypto": "^0.31.0", + "@cosmjs/encoding": "^0.31.0", + "@cosmjs/math": "^0.31.0", + "@cosmjs/proto-signing": "^0.31.0", + "@cosmjs/stargate": "^0.31.0", + "@cosmjs/tendermint-rpc": "^0.31.0", + "@cosmjs/utils": "^0.31.0", + "cosmjs-types": "^0.8.0", + "long": "^4.0.0", + "pako": "^2.0.2" + } + }, + "node_modules/@cosmjs/crypto": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.31.0.tgz", + "integrity": "sha512-UaqCe6Tgh0pe1QlZ66E13t6FlIF86QrnBXXq+EN7Xe1Rouza3fJ1ojGlPleJZkBoq3tAyYVIOOqdZIxtVj/sIQ==", + "dependencies": { + "@cosmjs/encoding": "^0.31.0", + "@cosmjs/math": "^0.31.0", + "@cosmjs/utils": "^0.31.0", + "@noble/hashes": "^1", + "bn.js": "^5.2.0", + "elliptic": "^6.5.4", + "libsodium-wrappers-sumo": "^0.7.11" + } + }, + "node_modules/@cosmjs/encoding": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.31.0.tgz", + "integrity": "sha512-NYGQDRxT7MIRSlcbAezwxK0FqnaSPKCH7O32cmfpHNWorFxhy9lwmBoCvoe59Kd0HmArI4h+NGzLEfX3OLnA4Q==", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" + } + }, + "node_modules/@cosmjs/json-rpc": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.31.0.tgz", + "integrity": "sha512-Ix2Cil2qysiLNrX+E0w3vtwCrqxGVq8jklpLA7B2vtMrw7tru/rS65fdFSy8ep0wUNLL6Ud32VXa5K0YObDOMA==", + "dependencies": { + "@cosmjs/stream": "^0.31.0", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/math": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.31.0.tgz", + "integrity": "sha512-Sb/8Ry/+gKJaYiV6X8q45kxXC9FoV98XCY1WXtu0JQwOi61VCG2VXsURQnVvZ/EhR/CuT/swOlNKrqEs3da0fw==", + "dependencies": { + "bn.js": "^5.2.0" + } + }, + "node_modules/@cosmjs/proto-signing": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.31.0.tgz", + "integrity": "sha512-JNlyOJRkn8EKB9mCthkjr6lVX6eyVQ09PFdmB4/DR874E62dFTvQ+YvyKMAgN7K7Dcjj26dVlAD3f6Xs7YOGDg==", + "dependencies": { + "@cosmjs/amino": "^0.31.0", + "@cosmjs/crypto": "^0.31.0", + "@cosmjs/encoding": "^0.31.0", + "@cosmjs/math": "^0.31.0", + "@cosmjs/utils": "^0.31.0", + "cosmjs-types": "^0.8.0", + "long": "^4.0.0" + } + }, + "node_modules/@cosmjs/socket": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.31.0.tgz", + "integrity": "sha512-WDh9gTyiP3OCXvSAJJn33+Ef3XqMWag+bpR1TdMBxTmlTxuvU+kPy4cf6P2OF+jkkUBEA5Se2EAju0eFbJMT+w==", + "dependencies": { + "@cosmjs/stream": "^0.31.0", + "isomorphic-ws": "^4.0.1", + "ws": "^7", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/stargate": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.31.0.tgz", + "integrity": "sha512-GYhk9lzZPj/QmYHC0VV/4AMoRzVcOP+EnB1YZCoWlBdLuVmpBYKRagJqWIrIwdk1E0gF2ZoESd2TYfdh1fqIpg==", + "dependencies": { + "@confio/ics23": "^0.6.8", + "@cosmjs/amino": "^0.31.0", + "@cosmjs/encoding": "^0.31.0", + "@cosmjs/math": "^0.31.0", + "@cosmjs/proto-signing": "^0.31.0", + "@cosmjs/stream": "^0.31.0", + "@cosmjs/tendermint-rpc": "^0.31.0", + "@cosmjs/utils": "^0.31.0", + "cosmjs-types": "^0.8.0", + "long": "^4.0.0", + "protobufjs": "~6.11.3", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/stream": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.31.0.tgz", + "integrity": "sha512-Y+aSHwhHkLGIaQOdqRob+yga2zr9ifl9gZDKD+B7+R5pdWN5f2TTDhYWxA6YZcZ6xRmfr7u8a7tDh7iYLC/zKA==", + "dependencies": { + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/tendermint-rpc": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.31.0.tgz", + "integrity": "sha512-yo9xbeuI6UoEKIhFZ9g0dvUKLqnBzwdpEc/uldQygQc51j38gQVwFko+6sjmhieJqRYYvrYumcbJMiV6GFM9aA==", + "dependencies": { + "@cosmjs/crypto": "^0.31.0", + "@cosmjs/encoding": "^0.31.0", + "@cosmjs/json-rpc": "^0.31.0", + "@cosmjs/math": "^0.31.0", + "@cosmjs/socket": "^0.31.0", + "@cosmjs/stream": "^0.31.0", + "@cosmjs/utils": "^0.31.0", + "axios": "^0.21.2", + "readonly-date": "^1.0.0", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/utils": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.31.0.tgz", + "integrity": "sha512-nNcycZWUYLNJlrIXgpcgVRqdl6BXjF4YlXdxobQWpW9Tikk61bEGeAFhDYtC0PwHlokCNw0KxWiHGJL4nL7Q5A==" + }, + "node_modules/@cosmos-kit/core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@cosmos-kit/core/-/core-2.1.0.tgz", + "integrity": "sha512-QFtVtzd2VXDQ55WfelPtMRdgnd3nalonEdcKnWe54GTCmyOa9zkADQFW7N48w6yoFDXZFPAnbIFoa5CEJo99CA==", + "dependencies": { + "@chain-registry/types": "0.13.0", + "@walletconnect/types": "2.7.2", + "bowser": "2.11.0", + "events": "3.3.0" + }, + "peerDependencies": { + "@cosmjs/amino": ">= 0.28", + "@cosmjs/cosmwasm-stargate": ">= 0.28", + "@cosmjs/proto-signing": ">= 0.28", + "@cosmjs/stargate": ">= 0.28", + "cosmjs-types": ">= 0.5" + } + }, + "node_modules/@cosmos-kit/core/node_modules/@chain-registry/types": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@chain-registry/types/-/types-0.13.0.tgz", + "integrity": "sha512-2xgKaRK6T3qkkzWkj2n5nHzGNl+0RuDDB8nS+oyssBe4tCq835yMkxrVAOivFfEm5YGl92FcaVDLrzmfPUO0MA==", + "dependencies": { + "@babel/runtime": "^7.19.4", + "@keplr-wallet/cosmos": "^0.11.12", + "@keplr-wallet/crypto": "^0.11.12" + } + }, + "node_modules/@cosmos-kit/keplr": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@cosmos-kit/keplr/-/keplr-2.1.0.tgz", + "integrity": "sha512-Y7Rz5QUlXvkPLAp3RgiiHTeRk16+O+5peosYGzbTE563j5Au8hl9y/mHuxk7z0Rtc++GjAnAzEar31FqCaeYhQ==", + "dependencies": { + "@cosmos-kit/keplr-extension": "^2.1.0", + "@cosmos-kit/keplr-mobile": "^2.1.0" + } + }, + "node_modules/@cosmos-kit/keplr-extension": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@cosmos-kit/keplr-extension/-/keplr-extension-2.1.0.tgz", + "integrity": "sha512-2heJlcKwcFCizhneqJKKYefDb8qvk0WzSv6Sgnqh4jnnXEU+Hh3+6jOCktjNY540naXIucEeICwa3kvTkqDp2w==", + "dependencies": { + "@chain-registry/keplr": "1.8.0", + "@cosmos-kit/core": "^2.1.0" + }, + "peerDependencies": { + "@cosmjs/amino": ">= 0.28", + "@cosmjs/proto-signing": ">= 0.28" + } + }, + "node_modules/@cosmos-kit/keplr-mobile": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@cosmos-kit/keplr-mobile/-/keplr-mobile-2.1.0.tgz", + "integrity": "sha512-i8SwDsaSGqo0b9y2Pk3mrsAQzl0Omt10LVaUryPKVYYzRqulcSbICV6bwsG5ZfYuLM7Su4qDuma+tupfKz3ijQ==", + "dependencies": { + "@chain-registry/keplr": "1.8.0", + "@cosmos-kit/core": "^2.1.0", + "@cosmos-kit/walletconnect": "^2.1.0" + }, + "peerDependencies": { + "@cosmjs/amino": ">= 0.28", + "@cosmjs/proto-signing": ">= 0.28" + } + }, + "node_modules/@cosmos-kit/react": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@cosmos-kit/react/-/react-2.1.1.tgz", + "integrity": "sha512-ZSpwVoEZDkJPJG+Ru4iR87v3WbRSOPgyf4wRq1zbp5kmNoezbjumoFuWRx2MpSvl0yYRfLlzpEqB3HGq5TTWYA==", + "dependencies": { + "@chain-registry/types": "0.13.1", + "@cosmos-kit/core": "^2.1.0", + "@cosmos-kit/react-lite": "^2.1.1", + "@interchain-ui/react": "1.3.0", + "@react-icons/all-files": "^4.1.0" + }, + "peerDependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + } + }, + "node_modules/@cosmos-kit/react-lite": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@cosmos-kit/react-lite/-/react-lite-2.1.1.tgz", + "integrity": "sha512-2wDkZYYGA45alR6xfd7nDizh8P3Sqmc0FlWLHS+Y6Gx66CRnsEoWejQz2kkakEai1PcNMefvkAJt9l5fCloUyg==", + "dependencies": { + "@chain-registry/types": "0.13.1", + "@cosmos-kit/core": "^2.1.0" + }, + "peerDependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + } + }, + "node_modules/@cosmos-kit/react/node_modules/@interchain-ui/react": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@interchain-ui/react/-/react-1.3.0.tgz", + "integrity": "sha512-17Forqigz0o0vUsg9b+oJoYiYTr5FLwCcj5VNivOBH4+Icg/IzAl7nR5UeCkcpXbd6QHdFPBZtijLKLmfj1O1Q==", + "dependencies": { + "@fastify/deepmerge": "^1.3.0", + "@formkit/auto-animate": "1.0.0-beta.6", + "@types/react-transition-group": "4.4.5", + "@vanilla-extract/css": "^1.12.0", + "@vanilla-extract/css-utils": "^0.1.3", + "@vanilla-extract/dynamic": "^2.0.3", + "@vanilla-extract/recipes": "^0.4.0", + "@zag-js/dialog": "^0.9.2", + "@zag-js/react": "^0.9.2", + "animejs": "^3.2.1", + "bignumber.js": "^9.1.1", + "clsx": "^1.2.1", + "copy-to-clipboard": "^3.3.3", + "immer": "^9.0.19", + "lodash": "^4.17.21", + "motion": "^10.16.2", + "polished": "^4.2.2", + "rainbow-sprinkles": "^0.17.0", + "zustand": "^4.3.8" + }, + "peerDependencies": { + "react": "^18.x", + "react-dom": "^18.x" + } + }, + "node_modules/@cosmos-kit/walletconnect": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@cosmos-kit/walletconnect/-/walletconnect-2.1.0.tgz", + "integrity": "sha512-/y+JBjGOi11uYJZsBvJZkC30EH6KBeo0bxPfbe8yLusdhItHavwjZlnv0BOVI0BA7mIIb38hAM1c3yQmS9g/pQ==", + "dependencies": { + "@babel/runtime": "7.11.2", + "@cosmos-kit/core": "^2.1.0", + "@walletconnect/sign-client": "^2.9.0", + "@walletconnect/types": "^2.9.0", + "@walletconnect/utils": "^2.9.0", + "events": "3.3.0" + }, + "peerDependencies": { + "@cosmjs/amino": ">= 0.28", + "@cosmjs/proto-signing": ">= 0.28" + } + }, + "node_modules/@cosmos-kit/walletconnect/node_modules/@babel/runtime": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + } + }, + "node_modules/@cosmos-kit/walletconnect/node_modules/@walletconnect/types": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.9.1.tgz", + "integrity": "sha512-xbGgTPuD6xsb7YMvCESBIH55cjB86QAnnVL50a/ED42YkQzDsOdJ0VGTbrm0tG5cxUOF933rpxZQjxGdP+ovww==", + "dependencies": { + "@walletconnect/events": "^1.0.1", + "@walletconnect/heartbeat": "1.2.1", + "@walletconnect/jsonrpc-types": "1.0.3", + "@walletconnect/keyvaluestorage": "^1.0.2", + "@walletconnect/logger": "^2.0.1", + "events": "^3.3.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@ethersproject/address": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", + "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", + "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", + "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", + "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ] + }, + "node_modules/@ethersproject/rlp": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", + "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@fastify/deepmerge": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-1.3.0.tgz", + "integrity": "sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==" + }, + "node_modules/@formkit/auto-animate": { + "version": "1.0.0-beta.6", + "resolved": "https://registry.npmjs.org/@formkit/auto-animate/-/auto-animate-1.0.0-beta.6.tgz", + "integrity": "sha512-PVDhLAlr+B4Xb7e+1wozBUWmXa6BFU8xUPR/W/E+TsQhPS1qkAdAsJ25keEnFrcePSnXHrOsh3tiFbEToOzV9w==" + }, + "node_modules/@headlessui/react": { + "version": "1.7.15", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.15.tgz", + "integrity": "sha512-OTO0XtoRQ6JPB1cKNFYBZv2Q0JMqMGNhYP1CjPvcJvjz8YGokz8oAj89HIYZGN0gZzn/4kk9iUpmMF4Q21Gsqw==", + "dependencies": { + "client-only": "^0.0.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16 || ^17 || ^18", + "react-dom": "^16 || ^17 || ^18" + } + }, + "node_modules/@interchain-ui/react": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@interchain-ui/react/-/react-1.3.3.tgz", + "integrity": "sha512-YMgbsa935yCM+vsK2SnZe220TRcDr8+Pm1xBwaQVwthUd2OWFMjB2ktJ+zrtT8pii6XlOZ5EMbE5M1BPQVGbAQ==", + "dependencies": { + "@fastify/deepmerge": "^1.3.0", + "@formkit/auto-animate": "1.0.0-beta.6", + "@vanilla-extract/css": "^1.12.0", + "@vanilla-extract/css-utils": "^0.1.3", + "@vanilla-extract/dynamic": "^2.0.3", + "@vanilla-extract/recipes": "^0.4.0", + "@zag-js/dialog": "^0.9.2", + "@zag-js/react": "^0.9.2", + "animejs": "^3.2.1", + "bignumber.js": "^9.1.1", + "clsx": "^1.2.1", + "copy-to-clipboard": "^3.3.3", + "immer": "^9.0.19", + "motion": "^10.16.2", + "rainbow-sprinkles": "^0.17.0", + "zustand": "^4.3.8" + }, + "peerDependencies": { + "react": "^18.x", + "react-dom": "^18.x" + } + }, + "node_modules/@iov/crypto": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@iov/crypto/-/crypto-2.1.0.tgz", + "integrity": "sha512-jnb4XuK50admolm7fBxOcxfAW2TO+wYrZlhDWiMETItY/Y5gNNa1zaDSO2wNIjjfGng+8nQ1yqnNhqy7busV2Q==", + "dependencies": { + "@iov/encoding": "^2.1.0", + "bip39": "^3.0.2", + "bn.js": "^4.11.8", + "elliptic": "^6.4.0", + "js-sha3": "^0.8.0", + "libsodium-wrappers": "^0.7.6", + "pbkdf2": "^3.0.16", + "ripemd160": "^2.0.2", + "sha.js": "^2.4.11", + "type-tagger": "^1.0.0", + "unorm": "^1.5.0" + } + }, + "node_modules/@iov/crypto/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/@iov/encoding": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@iov/encoding/-/encoding-2.1.0.tgz", + "integrity": "sha512-5IOdLO7Xg/uRykuiCqeMYghQ3IjWDtGxv7NTWXkgpHuna0aewx43mRpT2NPCpOZd1tpuorDtQ7/zbDNRaIIF/w==", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.3", + "bn.js": "^4.11.8", + "readonly-date": "^1.0.0" + } + }, + "node_modules/@iov/encoding/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/@iov/utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@iov/utils/-/utils-2.0.2.tgz", + "integrity": "sha512-4D8MEvTcFc/DVy5q25vHxRItmgJyeX85dixMH+MxdKr+yy71h3sYk+sVBEIn70uqGP7VqAJkGOPNFs08/XYELw==" + }, + "node_modules/@keplr-wallet/common": { + "version": "0.11.64", + "resolved": "https://registry.npmjs.org/@keplr-wallet/common/-/common-0.11.64.tgz", + "integrity": "sha512-kEnv6K+TxH+BBwwqUgiTcIXuRLBn6PaZMO4jwJbE1O8C8Qh/2j1QtkMLAMgl3Nj9qQkHgJ/dvA5oIqOIdLVMwg==", + "dependencies": { + "@keplr-wallet/crypto": "0.11.64", + "buffer": "^6.0.3", + "delay": "^4.4.0" + } + }, + "node_modules/@keplr-wallet/cosmos": { + "version": "0.11.64", + "resolved": "https://registry.npmjs.org/@keplr-wallet/cosmos/-/cosmos-0.11.64.tgz", + "integrity": "sha512-S6pLRaDKOyOFPfry7Km+Bgwr087gwHI4n3fp8NLGHtL75mLnOdeGvSEVW5LXJEWc5EyYgngM2CeS7xNHz+vjHg==", + "dependencies": { + "@ethersproject/address": "^5.6.0", + "@keplr-wallet/common": "0.11.64", + "@keplr-wallet/crypto": "0.11.64", + "@keplr-wallet/proto-types": "0.11.64", + "@keplr-wallet/types": "0.11.64", + "@keplr-wallet/unit": "0.11.64", + "axios": "^0.27.2", + "bech32": "^1.1.4", + "buffer": "^6.0.3", + "long": "^4.0.0", + "protobufjs": "^6.11.2" + } + }, + "node_modules/@keplr-wallet/cosmos/node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/@keplr-wallet/crypto": { + "version": "0.11.64", + "resolved": "https://registry.npmjs.org/@keplr-wallet/crypto/-/crypto-0.11.64.tgz", + "integrity": "sha512-DMeGhs+UUBpvefYa/0pF8h8D0lVS1T/eTGNKrn7SIO5CBMp1qfght+k1Se0pHGLr4CAtxFSXTDvYm3mr+ovKhg==", + "dependencies": { + "@ethersproject/keccak256": "^5.5.0", + "bip32": "^2.0.6", + "bip39": "^3.0.3", + "bs58check": "^2.1.2", + "buffer": "^6.0.3", + "crypto-js": "^4.0.0", + "elliptic": "^6.5.3", + "sha.js": "^2.4.11" + } + }, + "node_modules/@keplr-wallet/proto-types": { + "version": "0.11.64", + "resolved": "https://registry.npmjs.org/@keplr-wallet/proto-types/-/proto-types-0.11.64.tgz", + "integrity": "sha512-3oxfD1+zHPPuyKz41wt5A/gVhf2FQbA/L2u/4TxnmnITkY3IENirvMDrZUDJF0pWyGgZuXjhoVVFN2hMWI++PQ==", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "^6.11.2" + } + }, + "node_modules/@keplr-wallet/types": { + "version": "0.11.64", + "resolved": "https://registry.npmjs.org/@keplr-wallet/types/-/types-0.11.64.tgz", + "integrity": "sha512-GgzeLDHHfZFyne3O7UIfFHj/uYqVbxAZI31RbBwt460OBbvwQzjrlZwvJW3vieWRAgxKSITjzEDBl2WneFTQdQ==", + "dependencies": { + "axios": "^0.27.2", + "long": "^4.0.0" + } + }, + "node_modules/@keplr-wallet/types/node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/@keplr-wallet/unit": { + "version": "0.11.64", + "resolved": "https://registry.npmjs.org/@keplr-wallet/unit/-/unit-0.11.64.tgz", + "integrity": "sha512-BKTaDYI17QgEcBBCP5ZqsHsfNH29P6VMRxjR4nOXcJfhsuwvdJxa/p88VwQYbpVBw0oXcDOwudNiu7Bgf8w6QQ==", + "dependencies": { + "@keplr-wallet/types": "0.11.64", + "big-integer": "^1.6.48", + "utility-types": "^3.10.0" + } + }, + "node_modules/@mdx-js/mdx": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.3.0.tgz", + "integrity": "sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/mdx": "^2.0.0", + "estree-util-build-jsx": "^2.0.0", + "estree-util-is-identifier-name": "^2.0.0", + "estree-util-to-js": "^1.1.0", + "estree-walker": "^3.0.0", + "hast-util-to-estree": "^2.0.0", + "markdown-extensions": "^1.0.0", + "periscopic": "^3.0.0", + "remark-mdx": "^2.0.0", + "remark-parse": "^10.0.0", + "remark-rehype": "^10.0.0", + "unified": "^10.0.0", + "unist-util-position-from-estree": "^1.0.0", + "unist-util-stringify-position": "^3.0.0", + "unist-util-visit": "^4.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/react": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz", + "integrity": "sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g==", + "dependencies": { + "@types/mdx": "^2.0.0", + "@types/react": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "react": ">=16" + } + }, + "node_modules/@motionone/animation": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz", + "integrity": "sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ==", + "dependencies": { + "@motionone/easing": "^10.15.1", + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/dom": { + "version": "10.16.2", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.16.2.tgz", + "integrity": "sha512-bnuHdNbge1FutZXv+k7xub9oPWcF0hsu8y1HTH/qg6av58YI0VufZ3ngfC7p2xhMJMnoh0LXFma2EGTgPeCkeg==", + "dependencies": { + "@motionone/animation": "^10.15.1", + "@motionone/generators": "^10.15.1", + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/easing": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.15.1.tgz", + "integrity": "sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw==", + "dependencies": { + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/generators": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.15.1.tgz", + "integrity": "sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ==", + "dependencies": { + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/svelte": { + "version": "10.16.2", + "resolved": "https://registry.npmjs.org/@motionone/svelte/-/svelte-10.16.2.tgz", + "integrity": "sha512-38xsroKrfK+aHYhuQlE6eFcGy0EwrB43Q7RGjF73j/kRUTcLNu/LAaKiLLsN5lyqVzCgTBVt4TMT/ShWbTbc5Q==", + "dependencies": { + "@motionone/dom": "^10.16.2", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/types": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.15.1.tgz", + "integrity": "sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA==" + }, + "node_modules/@motionone/utils": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.15.1.tgz", + "integrity": "sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw==", + "dependencies": { + "@motionone/types": "^10.15.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/vue": { + "version": "10.16.2", + "resolved": "https://registry.npmjs.org/@motionone/vue/-/vue-10.16.2.tgz", + "integrity": "sha512-7/dEK/nWQXOkJ70bqb2KyNfSWbNvWqKKq1C8juj+0Mg/AorgD8O5wE3naddK0G+aXuNMqRuc4jlsYHHWHtIzVw==", + "dependencies": { + "@motionone/dom": "^10.16.2", + "tslib": "^2.3.1" + } + }, + "node_modules/@napi-rs/simple-git": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git/-/simple-git-0.1.8.tgz", + "integrity": "sha512-BvOMdkkofTz6lEE35itJ/laUokPhr/5ToMGlOH25YnhLD2yN1KpRAT4blW9tT8281/1aZjW3xyi73bs//IrDKA==", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@napi-rs/simple-git-android-arm-eabi": "0.1.8", + "@napi-rs/simple-git-android-arm64": "0.1.8", + "@napi-rs/simple-git-darwin-arm64": "0.1.8", + "@napi-rs/simple-git-darwin-x64": "0.1.8", + "@napi-rs/simple-git-linux-arm-gnueabihf": "0.1.8", + "@napi-rs/simple-git-linux-arm64-gnu": "0.1.8", + "@napi-rs/simple-git-linux-arm64-musl": "0.1.8", + "@napi-rs/simple-git-linux-x64-gnu": "0.1.8", + "@napi-rs/simple-git-linux-x64-musl": "0.1.8", + "@napi-rs/simple-git-win32-arm64-msvc": "0.1.8", + "@napi-rs/simple-git-win32-x64-msvc": "0.1.8" + } + }, + "node_modules/@napi-rs/simple-git-android-arm-eabi": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-android-arm-eabi/-/simple-git-android-arm-eabi-0.1.8.tgz", + "integrity": "sha512-JJCejHBB1G6O8nxjQLT4quWCcvLpC3oRdJJ9G3MFYSCoYS8i1bWCWeU+K7Br+xT+D6s1t9q8kNJAwJv9Ygpi0g==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-android-arm64": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-android-arm64/-/simple-git-android-arm64-0.1.8.tgz", + "integrity": "sha512-mraHzwWBw3tdRetNOS5KnFSjvdAbNBnjFLA8I4PwTCPJj3Q4txrigcPp2d59cJ0TC51xpnPXnZjYdNwwSI9g6g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-darwin-arm64": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-darwin-arm64/-/simple-git-darwin-arm64-0.1.8.tgz", + "integrity": "sha512-ufy/36eI/j4UskEuvqSH7uXtp3oXeLDmjQCfKJz3u5Vx98KmOMKrqAm2H81AB2WOtCo5mqS6PbBeUXR8BJX8lQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-darwin-x64": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-darwin-x64/-/simple-git-darwin-x64-0.1.8.tgz", + "integrity": "sha512-Vb21U+v3tPJNl+8JtIHHT8HGe6WZ8o1Tq3f6p+Jx9Cz71zEbcIiB9FCEMY1knS/jwQEOuhhlI9Qk7d4HY+rprA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-linux-arm-gnueabihf": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm-gnueabihf/-/simple-git-linux-arm-gnueabihf-0.1.8.tgz", + "integrity": "sha512-6BPTJ7CzpSm2t54mRLVaUr3S7ORJfVJoCk2rQ8v8oDg0XAMKvmQQxOsAgqKBo9gYNHJnqrOx3AEuEgvB586BuQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-linux-arm64-gnu": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm64-gnu/-/simple-git-linux-arm64-gnu-0.1.8.tgz", + "integrity": "sha512-qfESqUCAA/XoQpRXHptSQ8gIFnETCQt1zY9VOkplx6tgYk9PCeaX4B1Xuzrh3eZamSCMJFn+1YB9Ut8NwyGgAA==", + "cpu": [ + "arm64" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-linux-arm64-musl": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm64-musl/-/simple-git-linux-arm64-musl-0.1.8.tgz", + "integrity": "sha512-G80BQPpaRmQpn8dJGHp4I2/YVhWDUNJwcCrJAtAdbKFDCMyCHJBln2ERL/+IEUlIAT05zK/c1Z5WEprvXEdXow==", + "cpu": [ + "arm64" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-linux-x64-gnu": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-x64-gnu/-/simple-git-linux-x64-gnu-0.1.8.tgz", + "integrity": "sha512-NI6o1sZYEf6vPtNWJAm9w8BxJt+LlSFW0liSjYe3lc3e4dhMfV240f0ALeqlwdIldRPaDFwZSJX5/QbS7nMzhw==", + "cpu": [ + "x64" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-linux-x64-musl": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-x64-musl/-/simple-git-linux-x64-musl-0.1.8.tgz", + "integrity": "sha512-wljGAEOW41er45VTiU8kXJmO480pQKzsgRCvPlJJSCaEVBbmo6XXbFIXnZy1a2J3Zyy2IOsRB4PVkUZaNuPkZQ==", + "cpu": [ + "x64" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-win32-arm64-msvc": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-win32-arm64-msvc/-/simple-git-win32-arm64-msvc-0.1.8.tgz", + "integrity": "sha512-QuV4QILyKPfbWHoQKrhXqjiCClx0SxbCTVogkR89BwivekqJMd9UlMxZdoCmwLWutRx4z9KmzQqokvYI5QeepA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/simple-git-win32-x64-msvc": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-win32-x64-msvc/-/simple-git-win32-x64-msvc-0.1.8.tgz", + "integrity": "sha512-UzNS4JtjhZhZ5hRLq7BIUq+4JOwt1ThIKv11CsF1ag2l99f0123XvfEpjczKTaa94nHtjXYc2Mv9TjccBqYOew==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/env": { + "version": "13.4.8", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.8.tgz", + "integrity": "sha512-twuSf1klb3k9wXI7IZhbZGtFCWvGD4wXTY2rmvzIgVhXhs7ISThrbNyutBx3jWIL8Y/Hk9+woytFz5QsgtcRKQ==" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "13.4.8", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.8.tgz", + "integrity": "sha512-MSFplVM4dTWOuKAUv0XR9gY7AWtMSBu9os9f+kp+s5rWhM1I2CdR3obFttd6366nS/W/VZxbPM5oEIdlIa46zA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "13.4.8", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.8.tgz", + "integrity": "sha512-Reox+UXgonon9P0WNDE6w85DGtyBqGitl/ryznOvn6TvfxEaZIpTgeu3ZrJLU9dHSMhiK7YAM793mE/Zii2/Qw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "13.4.8", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.8.tgz", + "integrity": "sha512-kdyzYvAYtqQVgzIKNN7e1rLU8aZv86FDSRqPlOkKZlvqudvTO0iohuTPmnEEDlECeBM6qRPShNffotDcU/R2KA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "13.4.8", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.8.tgz", + "integrity": "sha512-oWxx4yRkUGcR81XwbI+T0zhZ3bDF6V1aVLpG+C7hSG50ULpV8gC39UxVO22/bv93ZlcfMY4zl8xkz9Klct6dpQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "13.4.8", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.8.tgz", + "integrity": "sha512-anhtvuO6eE9YRhYnaEGTfbpH3L5gT/9qPFcNoi6xS432r/4DAtpJY8kNktqkTVevVIC/pVumqO8tV59PR3zbNg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "13.4.8", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.8.tgz", + "integrity": "sha512-aR+J4wWfNgH1DwCCBNjan7Iumx0lLtn+2/rEYuhIrYLY4vnxqSVGz9u3fXcgUwo6Q9LT8NFkaqK1vPprdq+BXg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "13.4.8", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.8.tgz", + "integrity": "sha512-OWBKIrJwQBTqrat0xhxEB/jcsjJR3+diD9nc/Y8F1mRdQzsn4bPsomgJyuqPVZs6Lz3K18qdIkvywmfSq75SsQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "13.4.8", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.8.tgz", + "integrity": "sha512-agiPWGjUndXGTOn4ChbKipQXRA6/UPkywAWIkx7BhgGv48TiJfHTK6MGfBoL9tS6B4mtW39++uy0wFPnfD0JWg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "13.4.8", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.8.tgz", + "integrity": "sha512-UIRKoByVKbuR6SnFG4JM8EMFlJrfEGuUQ1ihxzEleWcNwRMMiVaCj1KyqfTOW8VTQhJ0u8P1Ngg6q1RwnIBTtw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@react-icons/all-files": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@react-icons/all-files/-/all-files-4.1.0.tgz", + "integrity": "sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ==", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/@stablelib/aead": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/aead/-/aead-1.0.1.tgz", + "integrity": "sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg==" + }, + "node_modules/@stablelib/binary": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/binary/-/binary-1.0.1.tgz", + "integrity": "sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==", + "dependencies": { + "@stablelib/int": "^1.0.1" + } + }, + "node_modules/@stablelib/bytes": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/bytes/-/bytes-1.0.1.tgz", + "integrity": "sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ==" + }, + "node_modules/@stablelib/chacha": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/chacha/-/chacha-1.0.1.tgz", + "integrity": "sha512-Pmlrswzr0pBzDofdFuVe1q7KdsHKhhU24e8gkEwnTGOmlC7PADzLVxGdn2PoNVBBabdg0l/IfLKg6sHAbTQugg==", + "dependencies": { + "@stablelib/binary": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/chacha20poly1305": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/chacha20poly1305/-/chacha20poly1305-1.0.1.tgz", + "integrity": "sha512-MmViqnqHd1ymwjOQfghRKw2R/jMIGT3wySN7cthjXCBdO+qErNPUBnRzqNpnvIwg7JBCg3LdeCZZO4de/yEhVA==", + "dependencies": { + "@stablelib/aead": "^1.0.1", + "@stablelib/binary": "^1.0.1", + "@stablelib/chacha": "^1.0.1", + "@stablelib/constant-time": "^1.0.1", + "@stablelib/poly1305": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/constant-time/-/constant-time-1.0.1.tgz", + "integrity": "sha512-tNOs3uD0vSJcK6z1fvef4Y+buN7DXhzHDPqRLSXUel1UfqMB1PWNsnnAezrKfEwTLpN0cGH2p9NNjs6IqeD0eg==" + }, + "node_modules/@stablelib/ed25519": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@stablelib/ed25519/-/ed25519-1.0.3.tgz", + "integrity": "sha512-puIMWaX9QlRsbhxfDc5i+mNPMY+0TmQEskunY1rZEBPi1acBCVQAhnsk/1Hk50DGPtVsZtAWQg4NHGlVaO9Hqg==", + "dependencies": { + "@stablelib/random": "^1.0.2", + "@stablelib/sha512": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/hash": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/hash/-/hash-1.0.1.tgz", + "integrity": "sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg==" + }, + "node_modules/@stablelib/hkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/hkdf/-/hkdf-1.0.1.tgz", + "integrity": "sha512-SBEHYE16ZXlHuaW5RcGk533YlBj4grMeg5TooN80W3NpcHRtLZLLXvKyX0qcRFxf+BGDobJLnwkvgEwHIDBR6g==", + "dependencies": { + "@stablelib/hash": "^1.0.1", + "@stablelib/hmac": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/hmac": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/hmac/-/hmac-1.0.1.tgz", + "integrity": "sha512-V2APD9NSnhVpV/QMYgCVMIYKiYG6LSqw1S65wxVoirhU/51ACio6D4yDVSwMzuTJXWZoVHbDdINioBwKy5kVmA==", + "dependencies": { + "@stablelib/constant-time": "^1.0.1", + "@stablelib/hash": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/int": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/int/-/int-1.0.1.tgz", + "integrity": "sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==" + }, + "node_modules/@stablelib/keyagreement": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/keyagreement/-/keyagreement-1.0.1.tgz", + "integrity": "sha512-VKL6xBwgJnI6l1jKrBAfn265cspaWBPAPEc62VBQrWHLqVgNRE09gQ/AnOEyKUWrrqfD+xSQ3u42gJjLDdMDQg==", + "dependencies": { + "@stablelib/bytes": "^1.0.1" + } + }, + "node_modules/@stablelib/poly1305": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/poly1305/-/poly1305-1.0.1.tgz", + "integrity": "sha512-1HlG3oTSuQDOhSnLwJRKeTRSAdFNVB/1djy2ZbS35rBSJ/PFqx9cf9qatinWghC2UbfOYD8AcrtbUQl8WoxabA==", + "dependencies": { + "@stablelib/constant-time": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/random": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@stablelib/random/-/random-1.0.2.tgz", + "integrity": "sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w==", + "dependencies": { + "@stablelib/binary": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/sha256": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/sha256/-/sha256-1.0.1.tgz", + "integrity": "sha512-GIIH3e6KH+91FqGV42Kcj71Uefd/QEe7Dy42sBTeqppXV95ggCcxLTk39bEr+lZfJmp+ghsR07J++ORkRELsBQ==", + "dependencies": { + "@stablelib/binary": "^1.0.1", + "@stablelib/hash": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/sha512": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/sha512/-/sha512-1.0.1.tgz", + "integrity": "sha512-13gl/iawHV9zvDKciLo1fQ8Bgn2Pvf7OV6amaRVKiq3pjQ3UmEpXxWiAfV8tYjUpeZroBxtyrwtdooQT/i3hzw==", + "dependencies": { + "@stablelib/binary": "^1.0.1", + "@stablelib/hash": "^1.0.1", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@stablelib/wipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/wipe/-/wipe-1.0.1.tgz", + "integrity": "sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==" + }, + "node_modules/@stablelib/x25519": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@stablelib/x25519/-/x25519-1.0.3.tgz", + "integrity": "sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw==", + "dependencies": { + "@stablelib/keyagreement": "^1.0.1", + "@stablelib/random": "^1.0.2", + "@stablelib/wipe": "^1.0.1" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz", + "integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@theguild/remark-mermaid": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@theguild/remark-mermaid/-/remark-mermaid-0.0.3.tgz", + "integrity": "sha512-fccVR6o4UPUztrBjdUhM4ahwx+X7YHhoxsUoXv2vI07vz4dq+I03Ot0SjuZzDA/H7engxcb8ZxzCUEkZgGr/2g==", + "dependencies": { + "mermaid": "^10.2.2", + "unist-util-visit": "^4.1.2" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/@types/acorn": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", + "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", + "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.0.tgz", + "integrity": "sha512-3qvGd0z8F2ENTGr/GG1yViqfiKmRfrXVx5sJyHGFu3z7m5g5utCQtGp/g29JnjflhtQJBv1WDQukHiT58xPcYQ==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", + "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/js-yaml": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", + "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==" + }, + "node_modules/@types/katex": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.14.0.tgz", + "integrity": "sha512-+2FW2CcT0K3P+JMR8YG846bmDwplKUTsWgT2ENwdQ1UdVfRk3GQrh6Mi4sTopy30gI8Uau5CEqHTDZ6YvWIUPA==" + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, + "node_modules/@types/mdast": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", + "integrity": "sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.5.tgz", + "integrity": "sha512-76CqzuD6Q7LC+AtbPqrvD9AqsN0k8bsYo2bM2J8pmNldP1aIPAbzUQ7QbobyXL4eLr1wK5x8FZFe8eF/ubRuBg==" + }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + }, + "node_modules/@types/node": { + "version": "18.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz", + "integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, + "node_modules/@types/react": { + "version": "18.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.14.tgz", + "integrity": "sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + }, + "node_modules/@types/unist": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", + "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" + }, + "node_modules/@vanilla-extract/css": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@vanilla-extract/css/-/css-1.12.0.tgz", + "integrity": "sha512-TEttZfnqTRtwgVYiBWQSGGUiVaYWReHp59DsavITEvh4TpJNifZFGhBznHx4wQFEsyio6xA513jps4tmqR6zmw==", + "dependencies": { + "@emotion/hash": "^0.9.0", + "@vanilla-extract/private": "^1.0.3", + "ahocorasick": "1.0.2", + "chalk": "^4.1.1", + "css-what": "^6.1.0", + "cssesc": "^3.0.0", + "csstype": "^3.0.7", + "deep-object-diff": "^1.1.9", + "deepmerge": "^4.2.2", + "media-query-parser": "^2.0.2", + "outdent": "^0.8.0" + } + }, + "node_modules/@vanilla-extract/css-utils": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@vanilla-extract/css-utils/-/css-utils-0.1.3.tgz", + "integrity": "sha512-PZAcHROlgtCUGI2y0JntdNwvPwCNyeVnkQu6KTYKdmxBbK3w72XJUmLFYapfaFfgami4I9CTLnrJTPdtmS3gpw==" + }, + "node_modules/@vanilla-extract/css/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@vanilla-extract/css/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@vanilla-extract/css/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@vanilla-extract/css/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@vanilla-extract/css/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@vanilla-extract/css/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@vanilla-extract/dynamic": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@vanilla-extract/dynamic/-/dynamic-2.0.3.tgz", + "integrity": "sha512-Rglfw2gXAYiBzAQ4jgUG7rBgE2c88e/zcG27ZVoIqMHVq56wf2C1katGMm1yFMNBgzqM7oBNYzz4YOMzznydkg==", + "dependencies": { + "@vanilla-extract/private": "^1.0.3" + } + }, + "node_modules/@vanilla-extract/private": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@vanilla-extract/private/-/private-1.0.3.tgz", + "integrity": "sha512-17kVyLq3ePTKOkveHxXuIJZtGYs+cSoev7BlP+Lf4916qfDhk/HBjvlYDe8egrea7LNPHKwSZJK/bzZC+Q6AwQ==" + }, + "node_modules/@vanilla-extract/recipes": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@vanilla-extract/recipes/-/recipes-0.4.0.tgz", + "integrity": "sha512-gFgB7BofUYbtbxINHK6DhMv1JDFDXp/YI/Xm+cqKar+1I/2dfxPepeDxSexL6YB4ftfeaDw8Kn5zydMvHcGOEQ==", + "peerDependencies": { + "@vanilla-extract/css": "^1.0.0" + } + }, + "node_modules/@walletconnect/core": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.9.1.tgz", + "integrity": "sha512-xyWeP0eLhEEDQAVJSmqs4n/AClKUM+8os2ZFe7BTuw1tFYjeLNVDtKCHziVOSTh8wEChMsKSGKA4zerQoH8mAQ==", + "dependencies": { + "@walletconnect/heartbeat": "1.2.1", + "@walletconnect/jsonrpc-provider": "1.0.13", + "@walletconnect/jsonrpc-types": "1.0.3", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "1.0.13", + "@walletconnect/keyvaluestorage": "^1.0.2", + "@walletconnect/logger": "^2.0.1", + "@walletconnect/relay-api": "^1.0.9", + "@walletconnect/relay-auth": "^1.0.4", + "@walletconnect/safe-json": "^1.0.2", + "@walletconnect/time": "^1.0.2", + "@walletconnect/types": "2.9.1", + "@walletconnect/utils": "2.9.1", + "events": "^3.3.0", + "lodash.isequal": "4.5.0", + "uint8arrays": "^3.1.0" + } + }, + "node_modules/@walletconnect/core/node_modules/@walletconnect/types": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.9.1.tgz", + "integrity": "sha512-xbGgTPuD6xsb7YMvCESBIH55cjB86QAnnVL50a/ED42YkQzDsOdJ0VGTbrm0tG5cxUOF933rpxZQjxGdP+ovww==", + "dependencies": { + "@walletconnect/events": "^1.0.1", + "@walletconnect/heartbeat": "1.2.1", + "@walletconnect/jsonrpc-types": "1.0.3", + "@walletconnect/keyvaluestorage": "^1.0.2", + "@walletconnect/logger": "^2.0.1", + "events": "^3.3.0" + } + }, + "node_modules/@walletconnect/environment": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/environment/-/environment-1.0.1.tgz", + "integrity": "sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/environment/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/events": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/events/-/events-1.0.1.tgz", + "integrity": "sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==", + "dependencies": { + "keyvaluestorage-interface": "^1.0.0", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/events/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/heartbeat": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@walletconnect/heartbeat/-/heartbeat-1.2.1.tgz", + "integrity": "sha512-yVzws616xsDLJxuG/28FqtZ5rzrTA4gUjdEMTbWB5Y8V1XHRmqq4efAxCw5ie7WjbXFSUyBHaWlMR+2/CpQC5Q==", + "dependencies": { + "@walletconnect/events": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/heartbeat/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/jsonrpc-provider": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.13.tgz", + "integrity": "sha512-K73EpThqHnSR26gOyNEL+acEex3P7VWZe6KE12ZwKzAt2H4e5gldZHbjsu2QR9cLeJ8AXuO7kEMOIcRv1QEc7g==", + "dependencies": { + "@walletconnect/jsonrpc-utils": "^1.0.8", + "@walletconnect/safe-json": "^1.0.2", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/jsonrpc-provider/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/jsonrpc-types": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.3.tgz", + "integrity": "sha512-iIQ8hboBl3o5ufmJ8cuduGad0CQm3ZlsHtujv9Eu16xq89q+BG7Nh5VLxxUgmtpnrePgFkTwXirCTkwJH1v+Yw==", + "dependencies": { + "keyvaluestorage-interface": "^1.0.0", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/jsonrpc-types/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/jsonrpc-utils": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz", + "integrity": "sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==", + "dependencies": { + "@walletconnect/environment": "^1.0.1", + "@walletconnect/jsonrpc-types": "^1.0.3", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/jsonrpc-utils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/jsonrpc-ws-connection": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.13.tgz", + "integrity": "sha512-mfOM7uFH4lGtQxG+XklYuFBj6dwVvseTt5/ahOkkmpcAEgz2umuzu7fTR+h5EmjQBdrmYyEBOWADbeaFNxdySg==", + "dependencies": { + "@walletconnect/jsonrpc-utils": "^1.0.6", + "@walletconnect/safe-json": "^1.0.2", + "events": "^3.3.0", + "tslib": "1.14.1", + "ws": "^7.5.1" + } + }, + "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/keyvaluestorage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.0.2.tgz", + "integrity": "sha512-U/nNG+VLWoPFdwwKx0oliT4ziKQCEoQ27L5Hhw8YOFGA2Po9A9pULUYNWhDgHkrb0gYDNt//X7wABcEWWBd3FQ==", + "dependencies": { + "safe-json-utils": "^1.1.1", + "tslib": "1.14.1" + }, + "peerDependencies": { + "@react-native-async-storage/async-storage": "1.x", + "lokijs": "1.x" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + }, + "lokijs": { + "optional": true + } + } + }, + "node_modules/@walletconnect/keyvaluestorage/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/logger": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/logger/-/logger-2.0.1.tgz", + "integrity": "sha512-SsTKdsgWm+oDTBeNE/zHxxr5eJfZmE9/5yp/Ku+zJtcTAjELb3DXueWkDXmE9h8uHIbJzIb5wj5lPdzyrjT6hQ==", + "dependencies": { + "pino": "7.11.0", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/logger/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/relay-api": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-api/-/relay-api-1.0.9.tgz", + "integrity": "sha512-Q3+rylJOqRkO1D9Su0DPE3mmznbAalYapJ9qmzDgK28mYF9alcP3UwG/og5V7l7CFOqzCLi7B8BvcBUrpDj0Rg==", + "dependencies": { + "@walletconnect/jsonrpc-types": "^1.0.2", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/relay-api/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/relay-auth": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-auth/-/relay-auth-1.0.4.tgz", + "integrity": "sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ==", + "dependencies": { + "@stablelib/ed25519": "^1.0.2", + "@stablelib/random": "^1.0.1", + "@walletconnect/safe-json": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "tslib": "1.14.1", + "uint8arrays": "^3.0.0" + } + }, + "node_modules/@walletconnect/relay-auth/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/safe-json": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/safe-json/-/safe-json-1.0.2.tgz", + "integrity": "sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/safe-json/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/sign-client": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.9.1.tgz", + "integrity": "sha512-Z7tFRrJ9btA1vU427vsjUS6cPlHQVcTWdKH90khEc2lv3dB6mU8FNO0VJsw+I2D7CW7WaMWF3nnj6Z1FfotbDg==", + "dependencies": { + "@walletconnect/core": "2.9.1", + "@walletconnect/events": "^1.0.1", + "@walletconnect/heartbeat": "1.2.1", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "^2.0.1", + "@walletconnect/time": "^1.0.2", + "@walletconnect/types": "2.9.1", + "@walletconnect/utils": "2.9.1", + "events": "^3.3.0" + } + }, + "node_modules/@walletconnect/sign-client/node_modules/@walletconnect/types": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.9.1.tgz", + "integrity": "sha512-xbGgTPuD6xsb7YMvCESBIH55cjB86QAnnVL50a/ED42YkQzDsOdJ0VGTbrm0tG5cxUOF933rpxZQjxGdP+ovww==", + "dependencies": { + "@walletconnect/events": "^1.0.1", + "@walletconnect/heartbeat": "1.2.1", + "@walletconnect/jsonrpc-types": "1.0.3", + "@walletconnect/keyvaluestorage": "^1.0.2", + "@walletconnect/logger": "^2.0.1", + "events": "^3.3.0" + } + }, + "node_modules/@walletconnect/time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/time/-/time-1.0.2.tgz", + "integrity": "sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/time/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/types": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.7.2.tgz", + "integrity": "sha512-1O2UefakZpT0ErRfEAXY7Ls3qdUrKDky/DsK088xR6klyfkQOx+aSVH0fJYLhmnqPTuvp3lrqNbsDc0s6/6nvg==", + "dependencies": { + "@walletconnect/events": "^1.0.1", + "@walletconnect/heartbeat": "1.2.1", + "@walletconnect/jsonrpc-types": "^1.0.2", + "@walletconnect/keyvaluestorage": "^1.0.2", + "@walletconnect/logger": "^2.0.1", + "events": "^3.3.0" + } + }, + "node_modules/@walletconnect/utils": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.9.1.tgz", + "integrity": "sha512-tXeQVebF5oPBvhdmuUyVSkSIBYx/egIi4czav1QrnUpwrUS1LsrFhyWBxSbhN7TXY287ULWkEf6aFpWOHdp5EA==", + "dependencies": { + "@stablelib/chacha20poly1305": "1.0.1", + "@stablelib/hkdf": "1.0.1", + "@stablelib/random": "^1.0.2", + "@stablelib/sha256": "1.0.1", + "@stablelib/x25519": "^1.0.3", + "@walletconnect/relay-api": "^1.0.9", + "@walletconnect/safe-json": "^1.0.2", + "@walletconnect/time": "^1.0.2", + "@walletconnect/types": "2.9.1", + "@walletconnect/window-getters": "^1.0.1", + "@walletconnect/window-metadata": "^1.0.1", + "detect-browser": "5.3.0", + "query-string": "7.1.3", + "uint8arrays": "^3.1.0" + } + }, + "node_modules/@walletconnect/utils/node_modules/@walletconnect/types": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.9.1.tgz", + "integrity": "sha512-xbGgTPuD6xsb7YMvCESBIH55cjB86QAnnVL50a/ED42YkQzDsOdJ0VGTbrm0tG5cxUOF933rpxZQjxGdP+ovww==", + "dependencies": { + "@walletconnect/events": "^1.0.1", + "@walletconnect/heartbeat": "1.2.1", + "@walletconnect/jsonrpc-types": "1.0.3", + "@walletconnect/keyvaluestorage": "^1.0.2", + "@walletconnect/logger": "^2.0.1", + "events": "^3.3.0" + } + }, + "node_modules/@walletconnect/window-getters": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-getters/-/window-getters-1.0.1.tgz", + "integrity": "sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/window-getters/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@walletconnect/window-metadata": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz", + "integrity": "sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==", + "dependencies": { + "@walletconnect/window-getters": "^1.0.1", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/window-metadata/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@zag-js/anatomy": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/anatomy/-/anatomy-0.9.2.tgz", + "integrity": "sha512-DgzZf4oo1/tdnSzUDu75pdxYep8WmgvxZi3h1Qa0hlu0erGvWPV0L7aAkdrau+Z3z4phc0FndieIDZN1oN1bEg==" + }, + "node_modules/@zag-js/aria-hidden": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/aria-hidden/-/aria-hidden-0.9.2.tgz", + "integrity": "sha512-Md+RCv8yOQ7uALjE8GRV0al3sb007aobFn1g6Vz0OSUD6Owsl4k1hwV1ZBWkSq6+OHhty35HROydqsKANDGc1g==", + "dependencies": { + "@zag-js/dom-query": "0.9.2" + } + }, + "node_modules/@zag-js/core": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/core/-/core-0.9.2.tgz", + "integrity": "sha512-L8MwOCuKnOdWqjSRlgb8HQYuD29yRmi0PrTip+T42YK4+SiBiROeGcExYH2txIpVCk3Gww8TU5TzOHDvKCACyA==", + "dependencies": { + "@zag-js/store": "0.9.2", + "klona": "2.0.6" + } + }, + "node_modules/@zag-js/dialog": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/dialog/-/dialog-0.9.2.tgz", + "integrity": "sha512-F7LrX2W5lSXukzRNnEL9z8E4zoHmqagrfP/o55jlM8+U/CVoLrRzTmPfl9b3ARguidkFIKj1ZgxZkphM9B0xoQ==", + "dependencies": { + "@zag-js/anatomy": "0.9.2", + "@zag-js/aria-hidden": "0.9.2", + "@zag-js/core": "0.9.2", + "@zag-js/dismissable": "0.9.2", + "@zag-js/dom-query": "0.9.2", + "@zag-js/remove-scroll": "0.9.2", + "@zag-js/types": "0.9.2", + "@zag-js/utils": "0.9.2", + "focus-trap": "7.4.1" + } + }, + "node_modules/@zag-js/dismissable": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/dismissable/-/dismissable-0.9.2.tgz", + "integrity": "sha512-e654TDrIMedzFawTF6o/o4Pdf5k78asE5nSBKri3FZqbHWmpCacLc+vil5d27nc7Y3BXRuM7AyAaFoyBnZ/IOw==", + "dependencies": { + "@zag-js/dom-event": "0.9.2", + "@zag-js/dom-query": "0.9.2", + "@zag-js/interact-outside": "0.9.2", + "@zag-js/utils": "0.9.2" + } + }, + "node_modules/@zag-js/dom-event": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/dom-event/-/dom-event-0.9.2.tgz", + "integrity": "sha512-2HUoIZw7Ig5bzm3S1f5i7S50LlyakhAD1seHBw6w+VwM7I6AFpbpJZjYAESeeKE+SAIA5q3CpdpL+KfdO5jpRg==", + "dependencies": { + "@zag-js/text-selection": "0.9.2", + "@zag-js/types": "0.9.2" + } + }, + "node_modules/@zag-js/dom-query": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-0.9.2.tgz", + "integrity": "sha512-N4K9sl3Dup+Jb0kaXrrwClwUdXgpgBb4xKYRDfG9HPO8ixX11Px8j4iTU3MdvhEt81sE7SkECdJNoyXaNxFqZA==" + }, + "node_modules/@zag-js/interact-outside": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/interact-outside/-/interact-outside-0.9.2.tgz", + "integrity": "sha512-UYaim/6dgqo5lUyfag5SeWqyGwGHyBgh7MC92eymI86Kb3BYOUhIfXEUaoaacFBxRuJbhmFEsxFF8bN/tWNTJw==", + "dependencies": { + "@zag-js/dom-event": "0.9.2", + "@zag-js/dom-query": "0.9.2", + "@zag-js/tabbable": "0.9.2", + "@zag-js/utils": "0.9.2" + } + }, + "node_modules/@zag-js/react": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/react/-/react-0.9.2.tgz", + "integrity": "sha512-7HBRfXQnPghWQwH/SY4MjUfRg8F6JaX/AosUA1mgUAi6WAIMEr8bIwb3iRVdRdjMoya/w3uynESpuimvo/7GFA==", + "dependencies": { + "@zag-js/core": "0.9.2", + "@zag-js/store": "0.9.2", + "@zag-js/types": "0.9.2", + "proxy-compare": "2.5.1" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/@zag-js/remove-scroll": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/remove-scroll/-/remove-scroll-0.9.2.tgz", + "integrity": "sha512-SJti7IWmsXQU58vlMOz6BxzfSVKjLWMf7TJB2S6B/vuxLqrDpVal4+K5kgYqwa2rmbf/NkR+4ocdLyF63YupUg==", + "dependencies": { + "@zag-js/dom-query": "0.9.2" + } + }, + "node_modules/@zag-js/store": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/store/-/store-0.9.2.tgz", + "integrity": "sha512-FO6BUK6ri0pZCEWqT8veiaZoTQwnCMqQ+C1pvf+ZtMnGMCjMXe/QvNUx/dcHSrscGckWJDBTJRbLhmDedyDPUA==", + "dependencies": { + "proxy-compare": "2.5.1" + } + }, + "node_modules/@zag-js/tabbable": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/tabbable/-/tabbable-0.9.2.tgz", + "integrity": "sha512-CekXUcJ7HqK+MIFXazBD7KIrntOIJZc8lscf3aXEkpbYfTmilad1ZORAR5tnsIkYIoDHcLdxhT69CKR87NMNFA==", + "dependencies": { + "@zag-js/dom-query": "0.9.2" + } + }, + "node_modules/@zag-js/text-selection": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/text-selection/-/text-selection-0.9.2.tgz", + "integrity": "sha512-xaXeLb9U7wZ5kEZ/L/if5INcX2YWi+Yzr8KIH2cNUaRE79cJFf0z1JG4D8VmO40EnCE396DVyNeLFdQXOAsu4Q==", + "dependencies": { + "@zag-js/dom-query": "0.9.2" + } + }, + "node_modules/@zag-js/types": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/types/-/types-0.9.2.tgz", + "integrity": "sha512-MM8KPTW5nX438fDb57K0DM+nxcLA9+WoFyE9A/fEaCH2kGsaVltmsY1ejolU4duYNOEQVon9T39QlGfgc81f/w==", + "dependencies": { + "csstype": "3.1.2" + } + }, + "node_modules/@zag-js/utils": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@zag-js/utils/-/utils-0.9.2.tgz", + "integrity": "sha512-PQZRIhgaowNrON7UF4u1JTABUhlWhMiu4uwN7S7SXcpyq1z8JXb4j5YEHNkH4F7lLMQAwmMdpJXHfjH5bYXR1Q==" + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ahocorasick": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ahocorasick/-/ahocorasick-1.0.2.tgz", + "integrity": "sha512-hCOfMzbFx5IDutmWLAt6MZwOUjIfSM9G9FyVxytmE4Rs/5YDPWQrD/+IR1w+FweD9H2oOZEnv36TmkjhNURBVA==" + }, + "node_modules/animejs": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/animejs/-/animejs-3.2.1.tgz", + "integrity": "sha512-sWno3ugFryK5nhiDm/2BKeFCpZv7vzerWUcUPyAZLDhMek3+S/p418ldZJbJXo5ZUOpfm2kP2XRO4NJcULMy9A==" + }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", + "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==" + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/arg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-1.0.0.tgz", + "integrity": "sha512-Wk7TEzl1KqvTGs/uyhmHO/3XLd3t1UeU4IstvPXVzGPM522cTjqjNZ99esCkcL52sjqjo8e8CTBcWhkxvGzoAw==" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/astring": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz", + "integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bignumber.js": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", + "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==", + "engines": { + "node": "*" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bip32": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", + "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", + "dependencies": { + "@types/node": "10.12.18", + "bs58check": "^2.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "tiny-secp256k1": "^1.1.3", + "typeforce": "^1.11.5", + "wif": "^2.0.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bip32/node_modules/@types/node": { + "version": "10.12.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" + }, + "node_modules/bip39": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", + "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", + "dependencies": { + "@noble/hashes": "^1.2.0" + } + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001512", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz", + "integrity": "sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chain-registry": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/chain-registry/-/chain-registry-1.18.0.tgz", + "integrity": "sha512-m80cUS7DM235FVxw82Vxf/9/j3qp8GXCQa7wtC55AaHdyajX/C0hWw513FVBKnMyCLPwLfMzC58eiFudBk888w==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@chain-registry/types": "^0.16.0" + } + }, + "node_modules/chain-registry/node_modules/@chain-registry/types": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@chain-registry/types/-/types-0.16.0.tgz", + "integrity": "sha512-4j6vq2Vqn/nF+UBjvRPUVs6eM3+5rJ+dPmEWpd/OoNH3wTy1k6aoilcSTZRR//vGcI5EOVGsxhhJxUzo2qqweA==", + "dependencies": { + "@babel/runtime": "^7.21.0" + } + }, + "node_modules/chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dependencies": { + "ansi-styles": "^3.1.0", + "escape-string-regexp": "^1.0.5", + "supports-color": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "engines": { + "node": "*" + } + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/clipboardy": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.2.tgz", + "integrity": "sha512-16KrBOV7bHmHdxcQiCvfUFYVFyEah4FI8vYT1Fr7CGSA4G+xBWMEfUEQJS1hxeHGtI9ju1Bzs9uXSbj5HZKArw==", + "dependencies": { + "arch": "^2.1.0", + "execa": "^0.8.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.0.3.tgz", + "integrity": "sha512-nadqwNxghAGTamwIqQSG433W6OADZx2vCo3UXHNrzTRHK/htu+7+L0zhjEoaeaQVNAi3YgqWDv8+tzf0hRfR+A==" + }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "dependencies": { + "layout-base": "^1.0.0" + } + }, + "node_modules/cosmjs-types": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.8.0.tgz", + "integrity": "sha512-Q2Mj95Fl0PYMWEhA2LuGEIhipF7mQwd9gTQ85DdP9jjjopeoGaDxvmPa5nakNzsq7FnO1DMTatXTAx6bxMH7Lg==", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "engines": { + "node": "*" + } + }, + "node_modules/crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "node_modules/curve25519-js": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/curve25519-js/-/curve25519-js-0.0.4.tgz", + "integrity": "sha512-axn2UMEnkhyDUPWOwVKBMVIzSQy2ejH2xRGy1wq81dqRwApXfIzfbE3hIX0ZRFBIihf/KDqK158DLwESu4AK1w==" + }, + "node_modules/cytoscape": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.25.0.tgz", + "integrity": "sha512-7MW3Iz57mCUo6JQCho6CmPBCbTlJr7LzyEtIkutG255HLVd4XuBg2I9BkTZLI/e4HoaOB/BiAzXuQybQ95+r9Q==", + "dependencies": { + "heap": "^0.2.6", + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==" + }, + "node_modules/d3": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz", + "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", + "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre-d3-es": { + "version": "7.0.10", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz", + "integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==", + "dependencies": { + "d3": "^7.8.2", + "lodash-es": "^4.17.21" + } + }, + "node_modules/dayjs": { + "version": "1.11.9", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", + "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-object-diff": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.9.tgz", + "integrity": "sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delaunator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", + "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", + "dependencies": { + "robust-predicates": "^3.0.0" + } + }, + "node_modules/delay": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/delay/-/delay-4.4.1.tgz", + "integrity": "sha512-aL3AhqtfhOlT/3ai6sWXeqwnw63ATNpnUiN4HL7x9q+My5QtHlO3OIkasmug9LKzpheLdmUKGRKnYXYAS7FQkQ==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-browser": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz", + "integrity": "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==" + }, + "node_modules/diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dompurify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz", + "integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ==" + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/elkjs": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz", + "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==" + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-2.1.1.tgz", + "integrity": "sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w==", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-2.2.2.tgz", + "integrity": "sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "estree-util-is-identifier-name": "^2.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.1.0.tgz", + "integrity": "sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-1.2.0.tgz", + "integrity": "sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-value-to-estree": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-1.3.0.tgz", + "integrity": "sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw==", + "dependencies": { + "is-plain-obj": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/estree-util-visit": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-1.2.1.tgz", + "integrity": "sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==", + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + }, + "node_modules/fast-redact": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", + "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/flexsearch": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/flexsearch/-/flexsearch-0.7.31.tgz", + "integrity": "sha512-XGozTsMPYkm+6b5QL3Z9wQcJjNYxp0CYn3U1gO7dwD6PAqU1SVWZxI9CCg3z+ml3YfqdPnrBehaBrnH2AGKbNA==" + }, + "node_modules/focus-trap": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.4.1.tgz", + "integrity": "sha512-rnXP5ERIjlo1gEZp7hQb4ekYqUxRuSDQeyWvxhahH3/GkWtd8h8g1C8Eu/KGpuvbUWNVeogK0kuzzrM4u2Z9jA==", + "dependencies": { + "tabbable": "^6.1.2" + } + }, + "node_modules/focus-visible": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/focus-visible/-/focus-visible-5.2.0.tgz", + "integrity": "sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==" + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/git-up": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", + "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", + "dependencies": { + "is-ssh": "^1.4.0", + "parse-url": "^8.1.0" + } + }, + "node_modules/git-url-parse": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz", + "integrity": "sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==", + "dependencies": { + "git-up": "^7.0.0" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==" + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-obj": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hash-obj/-/hash-obj-4.0.0.tgz", + "integrity": "sha512-FwO1BUVWkyHasWDW4S8o0ssQXjvyghLV2rfVhnN36b2bbcj45eGiuzdn9XOvOpjV3TKQD7Gm2BWNXdE9V4KKYg==", + "dependencies": { + "is-obj": "^3.0.0", + "sort-keys": "^5.0.0", + "type-fest": "^1.0.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hast-util-from-dom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-4.2.0.tgz", + "integrity": "sha512-t1RJW/OpJbCAJQeKi3Qrj1cAOLA0+av/iPFori112+0X7R3wng+jxLA+kXec8K4szqPRGI8vPxbbpEYvvpwaeQ==", + "dependencies": { + "hastscript": "^7.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-1.0.2.tgz", + "integrity": "sha512-LhrTA2gfCbLOGJq2u/asp4kwuG0y6NhWTXiPKP+n0qNukKy7hc10whqqCFfyvIA1Q5U5d0sp9HhNim9gglEH4A==", + "dependencies": { + "@types/hast": "^2.0.0", + "hast-util-from-parse5": "^7.0.0", + "parse5": "^7.0.0", + "vfile": "^5.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html-isomorphic": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-1.0.0.tgz", + "integrity": "sha512-Yu480AKeOEN/+l5LA674a+7BmIvtDj24GvOt7MtQWuhzUwlaaRWdEPXAh3Qm5vhuthpAipFb2vTetKXWOjmTvw==", + "dependencies": { + "@types/hast": "^2.0.0", + "hast-util-from-dom": "^4.0.0", + "hast-util-from-html": "^1.0.0", + "unist-util-remove-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz", + "integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/unist": "^2.0.0", + "hastscript": "^7.0.0", + "property-information": "^6.0.0", + "vfile": "^5.0.0", + "vfile-location": "^4.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz", + "integrity": "sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", + "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", + "dependencies": { + "@types/hast": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-2.3.3.tgz", + "integrity": "sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^2.0.0", + "@types/unist": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "estree-util-attach-comments": "^2.0.0", + "estree-util-is-identifier-name": "^2.0.0", + "hast-util-whitespace": "^2.0.0", + "mdast-util-mdx-expression": "^1.0.0", + "mdast-util-mdxjs-esm": "^1.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^0.4.1", + "unist-util-position": "^4.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-text": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-3.1.2.tgz", + "integrity": "sha512-tcllLfp23dJJ+ju5wCCZHVpzsQQ43+moJbqVX3jNWPB7z/KFC4FyZD6R7y94cHL6MQ33YtMZL8Z0aIXXI4XFTw==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/unist": "^2.0.0", + "hast-util-is-element": "^2.0.0", + "unist-util-find-after": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", + "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", + "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^3.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/heap": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", + "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==" + }, + "node_modules/hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/intersection-observer": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.12.2.tgz", + "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==" + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-3.0.0.tgz", + "integrity": "sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-reference": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.1.tgz", + "integrity": "sha512-baJJdQLiYaJdvFbJqXrcGv3WU3QCzBlUcI5QhbesIm6/xPsvmO+2CDoi/GMOFBQEQm+PXkwOPrp9KK5ozZsp2w==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/is-ssh": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", + "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==", + "dependencies": { + "protocols": "^2.0.1" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/js-crypto-env": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/js-crypto-env/-/js-crypto-env-0.3.2.tgz", + "integrity": "sha512-F1uHiCkSOo36qBuuZABA4sBf+xeFBzhJZ0Sd7af8FAruszIhm1Xxv+Zr5Ne90Zlh7/fnxCsrdkj0N8f0a3lVlQ==" + }, + "node_modules/js-crypto-hash": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/js-crypto-hash/-/js-crypto-hash-0.6.3.tgz", + "integrity": "sha512-SG8c9tM8y3sUb4k7WvpVfu5vU7zfPvX+eaYR5578TvehkehdaQbqAc+y+1FwxnqQ3WZ0gsYoOKp/mW+mqtNoWA==", + "dependencies": { + "buffer": "~5.4.3", + "hash.js": "~1.1.7", + "js-crypto-env": "^0.3.2", + "md5": "~2.2.1", + "sha3": "~2.1.0" + } + }, + "node_modules/js-crypto-hash/node_modules/buffer": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", + "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/js-crypto-hkdf": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/js-crypto-hkdf/-/js-crypto-hkdf-0.7.3.tgz", + "integrity": "sha512-eAaVArAjS2GCacWGXY4hjBiexrLQYlI0PMOcbwtrSEj84XU3kUfMYZm9bpTyaTXgdHC/eQoXe/Of6biG+RSEaQ==", + "dependencies": { + "js-crypto-env": "^0.3.2", + "js-crypto-hmac": "^0.6.3", + "js-crypto-random": "^0.4.3", + "js-encoding-utils": "0.5.6" + } + }, + "node_modules/js-crypto-hmac": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/js-crypto-hmac/-/js-crypto-hmac-0.6.3.tgz", + "integrity": "sha512-T0pKOaHACOSG6Xs6/06G8RDDeZouQwIQNBq9L/zoUGsd4F67gAjpT3q2lGigAGpUd1hiyy7vnhvLpz7VDt6DbA==", + "dependencies": { + "js-crypto-env": "^0.3.2", + "js-crypto-hash": "^0.6.3" + } + }, + "node_modules/js-crypto-random": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/js-crypto-random/-/js-crypto-random-0.4.3.tgz", + "integrity": "sha512-C3gzphPPfw9jfQ9Q/LjhJMZxQNp3AaoVRDvyZkiB+zYltfs8tKQPsskWkXACpg1Nzh01PtSRUvVijjptd2qGHQ==", + "dependencies": { + "js-crypto-env": "^0.3.2" + } + }, + "node_modules/js-encoding-utils": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/js-encoding-utils/-/js-encoding-utils-0.5.6.tgz", + "integrity": "sha512-qnAGsUIWrmzh5n+3AXqbxX1KsB9hkQmJZf3aA9DLAS7GpL/NEHCBreFFbW+imramoU+Q0TDyvkwhRbBRH1TVkg==" + }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" + }, + "node_modules/katex": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.8.tgz", + "integrity": "sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/keyvaluestorage-interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz", + "integrity": "sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==" + }, + "node_modules/khroma": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.0.0.tgz", + "integrity": "sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g==" + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==" + }, + "node_modules/libsodium": { + "version": "0.7.11", + "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.11.tgz", + "integrity": "sha512-WPfJ7sS53I2s4iM58QxY3Inb83/6mjlYgcmZs7DJsvDlnmVUwNinBCi5vBT43P6bHRy01O4zsMU2CoVR6xJ40A==" + }, + "node_modules/libsodium-sumo": { + "version": "0.7.11", + "resolved": "https://registry.npmjs.org/libsodium-sumo/-/libsodium-sumo-0.7.11.tgz", + "integrity": "sha512-bY+7ph7xpk51Ez2GbE10lXAQ5sJma6NghcIDaSPbM/G9elfrjLa0COHl/7P6Wb/JizQzl5UQontOOP1z0VwbLA==" + }, + "node_modules/libsodium-wrappers": { + "version": "0.7.11", + "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.11.tgz", + "integrity": "sha512-SrcLtXj7BM19vUKtQuyQKiQCRJPgbpauzl3s0rSwD+60wtHqSUuqcoawlMDheCJga85nKOQwxNYQxf/CKAvs6Q==", + "dependencies": { + "libsodium": "^0.7.11" + } + }, + "node_modules/libsodium-wrappers-sumo": { + "version": "0.7.11", + "resolved": "https://registry.npmjs.org/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.11.tgz", + "integrity": "sha512-DGypHOmJbB1nZn89KIfGOAkDgfv5N6SBGC3Qvmy/On0P0WD1JQvNRS/e3UL3aFF+xC0m+MYz5M+MnRnK2HMrKQ==", + "dependencies": { + "libsodium-sumo": "^0.7.11" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/markdown-extensions": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-1.1.1.tgz", + "integrity": "sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-table": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", + "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/match-sorter": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.1.tgz", + "integrity": "sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "remove-accents": "0.4.2" + } + }, + "node_modules/md5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha512-PlGG4z5mBANDGCKsYQe0CaUYHdZYZt8ZPZLmEt+Urf0W4GlpTX4HescwHU+dc9+Z/G/vZKYZYFrwgm9VxK6QOQ==", + "dependencies": { + "charenc": "~0.0.1", + "crypt": "~0.0.1", + "is-buffer": "~1.1.1" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/md5/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/mdast-util-definitions": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz", + "integrity": "sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==", + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.2.2.tgz", + "integrity": "sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==", + "dependencies": { + "@types/mdast": "^3.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", + "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "mdast-util-to-string": "^3.1.0", + "micromark": "^3.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-decode-string": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "unist-util-stringify-position": "^3.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-2.0.2.tgz", + "integrity": "sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==", + "dependencies": { + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-gfm-autolink-literal": "^1.0.0", + "mdast-util-gfm-footnote": "^1.0.0", + "mdast-util-gfm-strikethrough": "^1.0.0", + "mdast-util-gfm-table": "^1.0.0", + "mdast-util-gfm-task-list-item": "^1.0.0", + "mdast-util-to-markdown": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.3.tgz", + "integrity": "sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==", + "dependencies": { + "@types/mdast": "^3.0.0", + "ccount": "^2.0.0", + "mdast-util-find-and-replace": "^2.0.0", + "micromark-util-character": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.2.tgz", + "integrity": "sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==", + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-markdown": "^1.3.0", + "micromark-util-normalize-identifier": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.3.tgz", + "integrity": "sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==", + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-markdown": "^1.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.7.tgz", + "integrity": "sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==", + "dependencies": { + "@types/mdast": "^3.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-to-markdown": "^1.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.2.tgz", + "integrity": "sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==", + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-markdown": "^1.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-math": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-2.0.2.tgz", + "integrity": "sha512-8gmkKVp9v6+Tgjtq6SYx9kGPpTf6FVYRa53/DLh479aldR9AyP48qeVOgNZ5X7QUK7nOy4yw7vg6mbiGcs9jWQ==", + "dependencies": { + "@types/mdast": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-to-markdown": "^1.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-2.0.1.tgz", + "integrity": "sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw==", + "dependencies": { + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-mdx-expression": "^1.0.0", + "mdast-util-mdx-jsx": "^2.0.0", + "mdast-util-mdxjs-esm": "^1.0.0", + "mdast-util-to-markdown": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-1.3.2.tgz", + "integrity": "sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-to-markdown": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-2.1.4.tgz", + "integrity": "sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "ccount": "^2.0.0", + "mdast-util-from-markdown": "^1.1.0", + "mdast-util-to-markdown": "^1.3.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-remove-position": "^4.0.0", + "unist-util-stringify-position": "^3.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-1.3.1.tgz", + "integrity": "sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-to-markdown": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz", + "integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==", + "dependencies": { + "@types/mdast": "^3.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz", + "integrity": "sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-definitions": "^5.0.0", + "micromark-util-sanitize-uri": "^1.1.0", + "trim-lines": "^3.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz", + "integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==", + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^3.0.0", + "mdast-util-to-string": "^3.0.0", + "micromark-util-decode-string": "^1.0.0", + "unist-util-visit": "^4.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", + "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", + "dependencies": { + "@types/mdast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/media-query-parser": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/media-query-parser/-/media-query-parser-2.0.2.tgz", + "integrity": "sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w==", + "dependencies": { + "@babel/runtime": "^7.12.5" + } + }, + "node_modules/mermaid": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.2.4.tgz", + "integrity": "sha512-zHGjEI7lBvWZX+PQYmlhSA2p40OzW6QbGodTCSzDeVpqaTnyAC+2sRGqrpXO+uQk3CnoeClHQPraQUMStdqy2g==", + "dependencies": { + "@braintree/sanitize-url": "^6.0.2", + "cytoscape": "^3.23.0", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.1.0", + "d3": "^7.4.0", + "dagre-d3-es": "7.0.10", + "dayjs": "^1.11.7", + "dompurify": "3.0.3", + "elkjs": "^0.8.2", + "khroma": "^2.0.0", + "lodash-es": "^4.17.21", + "mdast-util-from-markdown": "^1.3.0", + "non-layered-tidy-tree-layout": "^2.0.2", + "stylis": "^4.1.3", + "ts-dedent": "^2.2.0", + "uuid": "^9.0.0", + "web-worker": "^1.2.0" + } + }, + "node_modules/micromark": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", + "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "micromark-core-commonmark": "^1.0.1", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", + "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-factory-destination": "^1.0.0", + "micromark-factory-label": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-factory-title": "^1.0.0", + "micromark-factory-whitespace": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-classify-character": "^1.0.0", + "micromark-util-html-tag-name": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.3.tgz", + "integrity": "sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^1.0.0", + "micromark-extension-gfm-footnote": "^1.0.0", + "micromark-extension-gfm-strikethrough": "^1.0.0", + "micromark-extension-gfm-table": "^1.0.0", + "micromark-extension-gfm-tagfilter": "^1.0.0", + "micromark-extension-gfm-task-list-item": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.5.tgz", + "integrity": "sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.1.2.tgz", + "integrity": "sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==", + "dependencies": { + "micromark-core-commonmark": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.7.tgz", + "integrity": "sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==", + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-classify-character": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.7.tgz", + "integrity": "sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.2.tgz", + "integrity": "sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==", + "dependencies": { + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.5.tgz", + "integrity": "sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-math": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-2.1.2.tgz", + "integrity": "sha512-es0CcOV89VNS9wFmyn+wyFTKweXGW4CEvdaAca6SWRWPyYCbBisnjaHLjWO4Nszuiud84jCpkHsqAJoa768Pvg==", + "dependencies": { + "@types/katex": "^0.16.0", + "katex": "^0.16.0", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-math/node_modules/@types/katex": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.0.tgz", + "integrity": "sha512-hz+S3nV6Mym5xPbT9fnO8dDhBFQguMYpY0Ipxv06JMi1ORgnEM4M1ymWDUhUNer3ElLmT583opRo4RzxKmh9jw==" + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-1.0.8.tgz", + "integrity": "sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "micromark-factory-mdx-expression": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-events-to-acorn": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-1.0.5.tgz", + "integrity": "sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA==", + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "estree-util-is-identifier-name": "^2.0.0", + "micromark-factory-mdx-expression": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-1.0.1.tgz", + "integrity": "sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA==", + "dependencies": { + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-1.0.1.tgz", + "integrity": "sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^1.0.0", + "micromark-extension-mdx-jsx": "^1.0.0", + "micromark-extension-mdx-md": "^1.0.0", + "micromark-extension-mdxjs-esm": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-1.0.5.tgz", + "integrity": "sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w==", + "dependencies": { + "@types/estree": "^1.0.0", + "micromark-core-commonmark": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-events-to-acorn": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "unist-util-position-from-estree": "^1.1.0", + "uvu": "^0.5.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", + "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", + "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-1.0.9.tgz", + "integrity": "sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-events-to-acorn": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "unist-util-position-from-estree": "^1.0.0", + "uvu": "^0.5.0", + "vfile-message": "^3.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", + "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", + "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", + "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", + "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", + "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", + "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", + "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", + "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-1.2.3.tgz", + "integrity": "sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "@types/unist": "^2.0.0", + "estree-util-visit": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0", + "vfile-message": "^3.0.0" + } + }, + "node_modules/micromark-util-html-tag-name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", + "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", + "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", + "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", + "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", + "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + }, + "node_modules/miscreant": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/miscreant/-/miscreant-0.3.2.tgz", + "integrity": "sha512-fL9KxsQz9BJB2KGPMHFrReioywkiomBiuaLk6EuChijK0BsJsIKJXdVomR+/bPj5mvbFD6wM0CM3bZio9g7OHA==" + }, + "node_modules/motion": { + "version": "10.16.2", + "resolved": "https://registry.npmjs.org/motion/-/motion-10.16.2.tgz", + "integrity": "sha512-p+PurYqfUdcJZvtnmAqu5fJgV2kR0uLFQuBKtLeFVTrYEVllI99tiOTSefVNYuip9ELTEkepIIDftNdze76NAQ==", + "dependencies": { + "@motionone/animation": "^10.15.1", + "@motionone/dom": "^10.16.2", + "@motionone/svelte": "^10.16.2", + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "@motionone/vue": "^10.16.2" + } + }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multiformats": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", + "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==" + }, + "node_modules/nan": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "13.4.8", + "resolved": "https://registry.npmjs.org/next/-/next-13.4.8.tgz", + "integrity": "sha512-lxUjndYKjZHGK3CWeN2RI+/6ni6EUvjiqGWXAYPxUfGIdFGQ5XoisrqAJ/dF74aP27buAfs8MKIbIMMdxjqSBg==", + "dependencies": { + "@next/env": "13.4.8", + "@swc/helpers": "0.5.1", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001406", + "postcss": "8.4.14", + "styled-jsx": "5.1.1", + "watchpack": "2.4.0", + "zod": "3.21.4" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=16.8.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "13.4.8", + "@next/swc-darwin-x64": "13.4.8", + "@next/swc-linux-arm64-gnu": "13.4.8", + "@next/swc-linux-arm64-musl": "13.4.8", + "@next/swc-linux-x64-gnu": "13.4.8", + "@next/swc-linux-x64-musl": "13.4.8", + "@next/swc-win32-arm64-msvc": "13.4.8", + "@next/swc-win32-ia32-msvc": "13.4.8", + "@next/swc-win32-x64-msvc": "13.4.8" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "fibers": ">= 3.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "fibers": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next-mdx-remote": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-4.4.1.tgz", + "integrity": "sha512-1BvyXaIou6xy3XoNF4yaMZUCb6vD2GTAa5ciOa6WoO+gAUTYsb1K4rI/HSC2ogAWLrb/7VSV52skz07vOzmqIQ==", + "dependencies": { + "@mdx-js/mdx": "^2.2.1", + "@mdx-js/react": "^2.2.1", + "vfile": "^5.3.0", + "vfile-matter": "^3.0.1" + }, + "engines": { + "node": ">=14", + "npm": ">=7" + }, + "peerDependencies": { + "react": ">=16.x <=18.x", + "react-dom": ">=16.x <=18.x" + } + }, + "node_modules/next-seo": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/next-seo/-/next-seo-6.1.0.tgz", + "integrity": "sha512-iMBpFoJsR5zWhguHJvsoBDxDSmdYTHtnVPB1ij+CD0NReQCP78ZxxbdL9qkKIf4oEuZEqZkrjAQLB0bkII7RYA==", + "peerDependencies": { + "next": "^8.1.1-canary.54 || >=9.0.0", + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/next-themes": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz", + "integrity": "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==", + "peerDependencies": { + "next": "*", + "react": "*", + "react-dom": "*" + } + }, + "node_modules/nextra": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nextra/-/nextra-2.8.0.tgz", + "integrity": "sha512-WyRNzw1IM/eF3M1H3LSsbZH97QsYYgj8upjx0f8hY6GspmPyPRAvBBscmXRt+7vye2oIYjfVwSiD1rj9amqq9Q==", + "dependencies": { + "@mdx-js/mdx": "^2.3.0", + "@mdx-js/react": "^2.3.0", + "@napi-rs/simple-git": "^0.1.8", + "@theguild/remark-mermaid": "^0.0.3", + "clsx": "^1.2.1", + "github-slugger": "^2.0.0", + "graceful-fs": "^4.2.11", + "gray-matter": "^4.0.3", + "katex": "^0.16.7", + "lodash.get": "^4.4.2", + "next-mdx-remote": "^4.2.1", + "p-limit": "^3.1.0", + "rehype-katex": "^6.0.3", + "rehype-pretty-code": "0.9.9", + "remark-gfm": "^3.0.1", + "remark-math": "^5.1.1", + "remark-reading-time": "^2.0.1", + "shiki": "^0.14.2", + "slash": "^3.0.0", + "title": "^3.5.3", + "unist-util-remove": "^3.1.1", + "unist-util-visit": "^4.1.1", + "zod": "^3.20.2" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "next": ">=9.5.3", + "react": ">=16.13.1", + "react-dom": ">=16.13.1" + } + }, + "node_modules/nextra-theme-docs": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nextra-theme-docs/-/nextra-theme-docs-2.8.0.tgz", + "integrity": "sha512-JoSAILDVp0GxeVWWZBFGoRijE2RcjZcXrMa47Fssi254T5wF+gm0HvEOSwrTaKaPaUL+IfshAiKglvXNKGzbNw==", + "dependencies": { + "@headlessui/react": "^1.7.10", + "@popperjs/core": "^2.11.6", + "clsx": "^1.2.1", + "flexsearch": "^0.7.21", + "focus-visible": "^5.2.0", + "git-url-parse": "^13.1.0", + "intersection-observer": "^0.12.2", + "match-sorter": "^6.3.1", + "next-seo": "^6.0.0", + "next-themes": "^0.2.1", + "scroll-into-view-if-needed": "^3.0.0", + "zod": "^3.20.2" + }, + "peerDependencies": { + "next": ">=9.5.3", + "nextra": "2.8.0", + "react": ">=16.13.1", + "react-dom": ">=16.13.1" + } + }, + "node_modules/non-layered-tidy-tree-layout": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", + "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==" + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/on-exit-leak-free": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz", + "integrity": "sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/outdent": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.8.0.tgz", + "integrity": "sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A==" + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" + }, + "node_modules/parse-path": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", + "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", + "dependencies": { + "protocols": "^2.0.0" + } + }, + "node_modules/parse-url": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", + "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", + "dependencies": { + "parse-path": "^7.0.0" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/periscopic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", + "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^3.0.0", + "is-reference": "^3.0.0" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/pino": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-7.11.0.tgz", + "integrity": "sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.0.0", + "on-exit-leak-free": "^0.2.0", + "pino-abstract-transport": "v0.5.0", + "pino-std-serializers": "^4.0.0", + "process-warning": "^1.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.1.0", + "safe-stable-stringify": "^2.1.0", + "sonic-boom": "^2.2.1", + "thread-stream": "^0.15.1" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz", + "integrity": "sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==", + "dependencies": { + "duplexify": "^4.1.2", + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", + "integrity": "sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==" + }, + "node_modules/polished": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", + "integrity": "sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==", + "dependencies": { + "@babel/runtime": "^7.17.8" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/process-warning": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", + "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==" + }, + "node_modules/property-information": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.2.0.tgz", + "integrity": "sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/protobufjs": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/protocols": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", + "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==" + }, + "node_modules/proxy-compare": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.5.1.tgz", + "integrity": "sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA==" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, + "node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, + "node_modules/rainbow-sprinkles": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/rainbow-sprinkles/-/rainbow-sprinkles-0.17.0.tgz", + "integrity": "sha512-ok3NrylQ0szvJtuBYaB/w09L9zOvvqcSQrvycT2A5XJxQNvwvkeADvTqQWGOQ3b6MkO8UmYccBPt8g8vVvxM9A==", + "peerDependencies": { + "@vanilla-extract/css": "^1", + "@vanilla-extract/dynamic": "^2" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/reading-time": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", + "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" + }, + "node_modules/readonly-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz", + "integrity": "sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ==" + }, + "node_modules/real-require": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.1.0.tgz", + "integrity": "sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/rehype-katex": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-6.0.3.tgz", + "integrity": "sha512-ByZlRwRUcWegNbF70CVRm2h/7xy7jQ3R9LaY4VVSvjnoVWwWVhNL60DiZsBpC5tSzYQOCvDbzncIpIjPZWodZA==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/katex": "^0.14.0", + "hast-util-from-html-isomorphic": "^1.0.0", + "hast-util-to-text": "^3.1.0", + "katex": "^0.16.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-pretty-code": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/rehype-pretty-code/-/rehype-pretty-code-0.9.9.tgz", + "integrity": "sha512-mlU2Qgupn9MMK31CTmWk0Ie5Vp0od+jh2vCkGDBMlPAMeAvYASn6Ois6xRmosutMT4yH/COc3R4r/PELpuUoWg==", + "dependencies": { + "@types/hast": "^2.0.0", + "hash-obj": "^4.0.0", + "parse-numeric-range": "^1.3.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "shiki": "*" + } + }, + "node_modules/remark-gfm": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz", + "integrity": "sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==", + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-gfm": "^2.0.0", + "micromark-extension-gfm": "^2.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-math": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-5.1.1.tgz", + "integrity": "sha512-cE5T2R/xLVtfFI4cCePtiRn+e6jKMtFDR3P8V3qpv8wpKjwvHoBA4eJzvX+nVrnlNy0911bdGmuspCSwetfYHw==", + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-math": "^2.0.0", + "micromark-extension-math": "^2.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-2.3.0.tgz", + "integrity": "sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==", + "dependencies": { + "mdast-util-mdx": "^2.0.0", + "micromark-extension-mdxjs": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz", + "integrity": "sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==", + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-reading-time": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-reading-time/-/remark-reading-time-2.0.1.tgz", + "integrity": "sha512-fy4BKy9SRhtYbEHvp6AItbRTnrhiDGbqLQTSYVbQPGuRCncU1ubSsh9p/W5QZSxtYcUXv8KGL0xBgPLyNJA1xw==", + "dependencies": { + "estree-util-is-identifier-name": "^2.0.0", + "estree-util-value-to-estree": "^1.3.0", + "reading-time": "^1.3.0", + "unist-util-visit": "^3.1.0" + } + }, + "node_modules/remark-reading-time/node_modules/unist-util-visit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-3.1.0.tgz", + "integrity": "sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-reading-time/node_modules/unist-util-visit-parents": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz", + "integrity": "sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-10.1.0.tgz", + "integrity": "sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-to-hast": "^12.1.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remove-accents": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", + "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, + "node_modules/sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-json-utils": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/safe-json-utils/-/safe-json-utils-1.1.1.tgz", + "integrity": "sha512-SAJWGKDs50tAbiDXLf89PDwt9XYkWyANFWVzn4dTXl5QyI8t2o/bW5/OJl3lvc2WVU4MEpTo9Yz5NVFNsp+OJQ==" + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.0.10.tgz", + "integrity": "sha512-t44QCeDKAPf1mtQH3fYpWz8IM/DyvHLjs8wUvvwMYxk5moOqCzrMSxK6HQVD0QVmVjXFavoFIPRVrMuJPKAvtg==", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, + "node_modules/secretjs": { + "version": "0.17.7", + "resolved": "https://registry.npmjs.org/secretjs/-/secretjs-0.17.7.tgz", + "integrity": "sha512-j39l9+vR2A8067QBqDDejS7LmRLgdkG4uRw2Ar6HMfzDGo26eTh7cIXVlVu/yHBumxtQzKun20epOXwuYHXjQg==", + "deprecated": "deprecated", + "dependencies": { + "@iov/crypto": "2.1.0", + "@iov/encoding": "2.1.0", + "@iov/utils": "2.0.2", + "axios": "0.21.1", + "curve25519-js": "0.0.4", + "fast-deep-equal": "3.1.1", + "js-crypto-hkdf": "0.7.3", + "miscreant": "0.3.2", + "pako": "1.0.11", + "protobufjs": "6.11.3", + "secure-random": "1.1.2" + } + }, + "node_modules/secretjs/node_modules/axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "dependencies": { + "follow-redirects": "^1.10.0" + } + }, + "node_modules/secretjs/node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/secure-random": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/secure-random/-/secure-random-1.1.2.tgz", + "integrity": "sha512-H2bdSKERKdBV1SwoqYm6C0y+9EA94v6SUBOWO8kDndc4NoUih7Dv6Tsgma7zO1lv27wIvjlD0ZpMQk7um5dheQ==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/sha3": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/sha3/-/sha3-2.1.4.tgz", + "integrity": "sha512-S8cNxbyb0UGUM2VhRD4Poe5N58gJnJsLJ5vC7FYWGUmGhcsj4++WaIOBFVDxlG0W3To6xBuiRh+i0Qp2oNCOtg==", + "dependencies": { + "buffer": "6.0.3" + } + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shiki": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.3.tgz", + "integrity": "sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==", + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/sonic-boom": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", + "integrity": "sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/sort-keys": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.0.0.tgz", + "integrity": "sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==", + "dependencies": { + "is-plain-obj": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sort-keys/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.3.tgz", + "integrity": "sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/style-to-object": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.1.tgz", + "integrity": "sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw==", + "dependencies": { + "inline-style-parser": "0.1.1" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/stylis": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz", + "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==" + }, + "node_modules/supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw==", + "dependencies": { + "has-flag": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/symbol-observable": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz", + "integrity": "sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" + }, + "node_modules/thread-stream": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-0.15.2.tgz", + "integrity": "sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==", + "dependencies": { + "real-require": "^0.1.0" + } + }, + "node_modules/tiny-secp256k1": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", + "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.3.0", + "bn.js": "^4.11.8", + "create-hmac": "^1.1.7", + "elliptic": "^6.4.0", + "nan": "^2.13.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/tiny-secp256k1/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/title": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/title/-/title-3.5.3.tgz", + "integrity": "sha512-20JyowYglSEeCvZv3EZ0nZ046vLarO37prvV0mbtQV7C8DJPGgN967r8SJkqd3XK3K3lD3/Iyfp3avjfil8Q2Q==", + "dependencies": { + "arg": "1.0.0", + "chalk": "2.3.0", + "clipboardy": "1.2.2", + "titleize": "1.0.0" + }, + "bin": { + "title": "bin/title.js" + } + }, + "node_modules/titleize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.0.tgz", + "integrity": "sha512-TARUb7z1pGvlLxgPk++7wJ6aycXF3GJ0sNSBTAsTuJrQG5QuZlkUQP+zl+nbjAh4gMX9yDw9ZYklMd7vAfJKEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", + "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "engines": { + "node": ">=6.10" + } + }, + "node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, + "node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-tagger": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/type-tagger/-/type-tagger-1.0.0.tgz", + "integrity": "sha512-FIPqqpmDgdaulCnRoKv1/d3U4xVBUrYn42QXWNP3XYmgfPUDuBUsgFOb9ntT0aIe0UsUP+lknpQ5d9Kn36RssA==" + }, + "node_modules/typeforce": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", + "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uint8arrays": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz", + "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/unified": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", + "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", + "dependencies": { + "@types/unist": "^2.0.0", + "bail": "^2.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unified/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unist-util-find-after": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-4.0.1.tgz", + "integrity": "sha512-QO/PuPMm2ERxC6vFXEPtmAutOopy5PknD+Oq64gGwxKtk4xwo9Z97t9Av1obPmGU0IyTa6EKYUfTrK2QJS3Ozw==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-generated": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", + "integrity": "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", + "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz", + "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.2.tgz", + "integrity": "sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-3.1.1.tgz", + "integrity": "sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-4.0.2.tgz", + "integrity": "sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", + "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", + "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^5.1.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", + "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unorm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", + "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utility-types": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", + "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/uvu": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", + "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", + "dependencies": { + "dequal": "^2.0.0", + "diff": "^5.0.0", + "kleur": "^4.0.3", + "sade": "^1.7.3" + }, + "bin": { + "uvu": "bin.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/vfile": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", + "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", + "dependencies": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^3.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz", + "integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==", + "dependencies": { + "@types/unist": "^2.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-matter": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile-matter/-/vfile-matter-3.0.1.tgz", + "integrity": "sha512-CAAIDwnh6ZdtrqAuxdElUqQRQDQgbbIrYtDYI8gCjXS1qQ+1XdLoK8FIZWxJwn0/I+BkSSZpar3SOgjemQz4fg==", + "dependencies": { + "@types/js-yaml": "^4.0.0", + "is-buffer": "^2.0.0", + "js-yaml": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-matter/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/vfile-matter/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/vfile-message": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", + "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==" + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==" + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/web-worker": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", + "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==" + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/wif": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", + "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", + "dependencies": { + "bs58check": "<3.0.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xstream": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/xstream/-/xstream-11.14.0.tgz", + "integrity": "sha512-1bLb+kKKtKPbgTK6i/BaoAn03g47PpFstlbe1BA+y3pNS/LfvcaghS5BFf9+EE1J+KwSQsEpfJvFN5GqFtiNmw==", + "dependencies": { + "globalthis": "^1.0.1", + "symbol-observable": "^2.0.3" + } + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", + "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zustand": { + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.3.9.tgz", + "integrity": "sha512-Tat5r8jOMG1Vcsj8uldMyqYKC5IZvQif8zetmLHs9WoZlntTHmIoNM8TpLRY31ExncuUvUOXehd0kvahkuHjDw==", + "dependencies": { + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "immer": ">=9.0", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/sdk/typescript/docs/package.json b/sdk/typescript/docs/package.json new file mode 100644 index 0000000000..a33f6f33d0 --- /dev/null +++ b/sdk/typescript/docs/package.json @@ -0,0 +1,29 @@ +{ + "name": "nym-sdk-docs", + "version": "0.0.1", + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "lint:fix": "next lint --fix", + "docs:prod:build": "./scripts/build-prod-docs.sh" + }, + "dependencies": { + "@cosmjs/amino": "^0.31.0", + "@cosmjs/cosmwasm-stargate": "^0.31.0", + "@cosmos-kit/keplr": "^2.1.0", + "@cosmos-kit/react": "^2.1.1", + "@interchain-ui/react": "^1.3.3", + "chain-registry": "^1.18.0", + "next": "^13.0.6", + "nextra": "latest", + "nextra-theme-docs": "latest", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/node": "18.11.10", + "typescript": "^4.9.3" + } +} diff --git a/sdk/typescript/docs/pages/_meta.json b/sdk/typescript/docs/pages/_meta.json new file mode 100644 index 0000000000..3d07d952be --- /dev/null +++ b/sdk/typescript/docs/pages/_meta.json @@ -0,0 +1,6 @@ +{ + "index": "Introduction", + "sdk": "Typescript SDK", + "examples": "Example usage and apps", + "blockchain": "Nym Cosmos chain" +} diff --git a/sdk/typescript/docs/pages/blockchain/_meta.json b/sdk/typescript/docs/pages/blockchain/_meta.json new file mode 100644 index 0000000000..4f8abbb472 --- /dev/null +++ b/sdk/typescript/docs/pages/blockchain/_meta.json @@ -0,0 +1,3 @@ +{ + "wallet": "Wallet support" +} diff --git a/sdk/typescript/docs/pages/blockchain/wallet.mdx b/sdk/typescript/docs/pages/blockchain/wallet.mdx new file mode 100644 index 0000000000..5e7bbe91a8 --- /dev/null +++ b/sdk/typescript/docs/pages/blockchain/wallet.mdx @@ -0,0 +1,13 @@ + +You can try out interacting with the Nyx chain that runs the Nym smart contracts by connecting your wallet: + +```tsx +// TODO - move this out of fencing and fix up compile errors + +import { Wallet } from '../components/wallet'; + + +``` + +Nulla reprehenderit nostrud culpa consectetur culpa occaecat tempor culpa tempor eiusmod. Ullamco amet labore culpa ipsum ullamco veniam ex sunt et. Pariatur qui consectetur commodo irure non laboris officia in ex dolor eu. Quis est quis eiusmod non cillum ea aliqua amet excepteur deserunt. Esse commodo anim Lorem enim nostrud veniam ex cillum commodo proident laboris ad dolore. Lorem ea veniam ex cillum adipisicing ut sunt minim voluptate cupidatat labore voluptate eiusmod irure. Laborum ipsum ullamco fugiat elit ullamco officia laborum nulla aute ea et tempor labore id. + diff --git a/sdk/typescript/docs/pages/examples/_meta.json b/sdk/typescript/docs/pages/examples/_meta.json new file mode 100644 index 0000000000..1a0898b0b9 --- /dev/null +++ b/sdk/typescript/docs/pages/examples/_meta.json @@ -0,0 +1,5 @@ +{ + "index": "List of live examples", + "community": "Apps made by the Nym community", + "playground": "Interactive playground" +} diff --git a/sdk/typescript/docs/pages/examples/community.mdx b/sdk/typescript/docs/pages/examples/community.mdx new file mode 100644 index 0000000000..e5e5f3fb87 --- /dev/null +++ b/sdk/typescript/docs/pages/examples/community.mdx @@ -0,0 +1,8 @@ +# Community Typescript and Javascript apps + +Here is a list of apps built by our awesome community using the Nym Typescript SDK: + +- project 1 +- project 2 +- project 3 + diff --git a/sdk/typescript/docs/pages/examples/index.mdx b/sdk/typescript/docs/pages/examples/index.mdx new file mode 100644 index 0000000000..05e56d947c --- /dev/null +++ b/sdk/typescript/docs/pages/examples/index.mdx @@ -0,0 +1,12 @@ +# Examples + +Here are some live examples of what you can do with the Typescript SDK: + +- Chat app +- Node tester +- mixFetch demo + +And some examples of usage: + +- Firefox browser extension +- Chrome browser extension diff --git a/sdk/typescript/docs/pages/examples/playground.mdx b/sdk/typescript/docs/pages/examples/playground.mdx new file mode 100644 index 0000000000..3200695a3b --- /dev/null +++ b/sdk/typescript/docs/pages/examples/playground.mdx @@ -0,0 +1,7 @@ +# Try out the Typescript SDK live in your browser + +Commodo magna ullamco voluptate aute adipisicing culpa duis reprehenderit. Laboris fugiat in duis mollit dolor voluptate ex anim. Cupidatat enim nostrud laboris incididunt minim do do et adipisicing. Adipisicing pariatur dolor elit nisi elit. Cillum nisi irure officia ipsum. Pariatur ex esse dolor sit esse consectetur dolore dolor. Nostrud dolor proident ullamco sint commodo laboris culpa. + +Occaecat commodo deserunt ut laborum pariatur exercitation ea cillum officia non. Cupidatat amet aute ex exercitation magna quis fugiat consequat minim exercitation fugiat deserunt Lorem deserunt. Commodo irure incididunt officia et aute. + +Ut voluptate deserunt sunt voluptate elit. Incididunt enim nulla amet occaecat incididunt officia sunt eu fugiat dolore id anim. Aliqua duis voluptate consectetur ex voluptate nisi sit quis esse nulla irure aliquip. diff --git a/sdk/typescript/docs/pages/index.mdx b/sdk/typescript/docs/pages/index.mdx new file mode 100644 index 0000000000..a36b03cc62 --- /dev/null +++ b/sdk/typescript/docs/pages/index.mdx @@ -0,0 +1,3 @@ +# Introduction + +Welcome to the documentation for the Nym Typescript SDK. diff --git a/sdk/typescript/docs/pages/sdk/_meta.json b/sdk/typescript/docs/pages/sdk/_meta.json new file mode 100644 index 0000000000..fc58278791 --- /dev/null +++ b/sdk/typescript/docs/pages/sdk/_meta.json @@ -0,0 +1,5 @@ +{ + "index": "Introduction", + "mix-fetch": "mixFetch", + "react": "React" +} diff --git a/sdk/typescript/docs/pages/sdk/index.mdx b/sdk/typescript/docs/pages/sdk/index.mdx new file mode 100644 index 0000000000..f55fd65cca --- /dev/null +++ b/sdk/typescript/docs/pages/sdk/index.mdx @@ -0,0 +1,9 @@ +# Nym Typescript SDK + +Commodo magna ullamco voluptate aute adipisicing culpa duis reprehenderit. Laboris fugiat in duis mollit dolor voluptate ex anim. Cupidatat enim nostrud laboris incididunt minim do do et adipisicing. Adipisicing pariatur dolor elit nisi elit. Cillum nisi irure officia ipsum. Pariatur ex esse dolor sit esse consectetur dolore dolor. Nostrud dolor proident ullamco sint commodo laboris culpa. + +Occaecat commodo deserunt ut laborum pariatur exercitation ea cillum officia non. Cupidatat amet aute ex exercitation magna quis fugiat consequat minim exercitation fugiat deserunt Lorem deserunt. Commodo irure incididunt officia et aute. + +Ut voluptate deserunt sunt voluptate elit. Incididunt enim nulla amet occaecat incididunt officia sunt eu fugiat dolore id anim. Aliqua duis voluptate consectetur ex voluptate nisi sit quis esse nulla irure aliquip. + +Culpa proident aliqua eu in. Id Lorem eu nostrud cupidatat sint adipisicing ex esse tempor commodo. Enim labore commodo aute quis aliqua enim. Veniam minim sunt commodo cillum quis officia ea tempor adipisicing pariatur. Nisi ea in reprehenderit in nostrud. Mollit non proident cupidatat aliqua ut ea quis id exercitation labore excepteur nulla ex. diff --git a/sdk/typescript/docs/pages/sdk/mix-fetch.mdx b/sdk/typescript/docs/pages/sdk/mix-fetch.mdx new file mode 100644 index 0000000000..8ca721850d --- /dev/null +++ b/sdk/typescript/docs/pages/sdk/mix-fetch.mdx @@ -0,0 +1,8 @@ +--- +description: Send your HTTP requests over the Nym mixnet securely with a drop-in replacement for fetch +--- + +# mixFetch + +Anim occaecat exercitation officia aliquip sit culpa incididunt labore sit aute sint incididunt consequat. Ex enim ullamco dolore laboris incididunt aliqua duis consectetur non voluptate. Dolore ut sunt ad commodo. Veniam enim culpa tempor consectetur excepteur pariatur adipisicing. Commodo adipisicing magna irure deserunt cupidatat excepteur cupidatat consectetur fugiat irure aliqua laboris qui. Officia incididunt adipisicing elit eu fugiat cupidatat non irure id dolor. + diff --git a/sdk/typescript/docs/pages/sdk/node-tester.mdx b/sdk/typescript/docs/pages/sdk/node-tester.mdx new file mode 100644 index 0000000000..374a0dae0e --- /dev/null +++ b/sdk/typescript/docs/pages/sdk/node-tester.mdx @@ -0,0 +1,3 @@ +# Node Tester + +Deserunt commodo tempor magna culpa qui consectetur reprehenderit. Pariatur ipsum nostrud mollit ex elit est reprehenderit enim deserunt. Et voluptate veniam proident sunt ea in. Aute aliquip do commodo aliqua duis Lorem. Ut sunt officia exercitation magna nisi ea commodo do nostrud ullamco cupidatat tempor est. Magna minim magna minim occaecat. Tempor nisi occaecat amet duis duis qui deserunt culpa ex. diff --git a/sdk/typescript/docs/pages/sdk/react/_meta.json b/sdk/typescript/docs/pages/sdk/react/_meta.json new file mode 100644 index 0000000000..d3673f13ea --- /dev/null +++ b/sdk/typescript/docs/pages/sdk/react/_meta.json @@ -0,0 +1,3 @@ +{ + "index": "Introduction" +} diff --git a/sdk/typescript/docs/pages/sdk/react/components.mdx b/sdk/typescript/docs/pages/sdk/react/components.mdx new file mode 100644 index 0000000000..cb09ef1200 --- /dev/null +++ b/sdk/typescript/docs/pages/sdk/react/components.mdx @@ -0,0 +1,9 @@ +# Nym React Components + +Voluptate laborum sit deserunt mollit labore ex labore sunt. Aliquip culpa est veniam culpa dolore irure do veniam aliquip ullamco reprehenderit pariatur. Elit proident sit ullamco dolore deserunt aute minim. Irure consectetur minim elit et incididunt non fugiat ad deserunt consectetur ad. Veniam enim non ipsum duis anim duis duis cillum consectetur anim eiusmod sint veniam. Amet commodo dolor esse amet dolor quis labore elit. Tempor commodo ipsum enim consectetur sit culpa consequat nisi. + +UI to show: +- address display +- address form text input (with validation) +- currency display +- currency form text input (with validation) diff --git a/sdk/typescript/docs/pages/sdk/react/hooks.mdx b/sdk/typescript/docs/pages/sdk/react/hooks.mdx new file mode 100644 index 0000000000..53c6ceab8a --- /dev/null +++ b/sdk/typescript/docs/pages/sdk/react/hooks.mdx @@ -0,0 +1,3 @@ +# React Hooks for the SDK + +Voluptate laborum sit deserunt mollit labore ex labore sunt. Aliquip culpa est veniam culpa dolore irure do veniam aliquip ullamco reprehenderit pariatur. Elit proident sit ullamco dolore deserunt aute minim. Irure consectetur minim elit et incididunt non fugiat ad deserunt consectetur ad. Veniam enim non ipsum duis anim duis duis cillum consectetur anim eiusmod sint veniam. Amet commodo dolor esse amet dolor quis labore elit. Tempor commodo ipsum enim consectetur sit culpa consequat nisi. diff --git a/sdk/typescript/docs/pages/sdk/react/index.mdx b/sdk/typescript/docs/pages/sdk/react/index.mdx new file mode 100644 index 0000000000..9d94d539ac --- /dev/null +++ b/sdk/typescript/docs/pages/sdk/react/index.mdx @@ -0,0 +1,9 @@ +# React support + +Nym provides several React libraries: + + +We also suggest you look at [CosmosKit](https://docs.cosmoskit.com/) if you want to: +- use a wallet (Keplr, Cosmostation) in your app +- sign transactions with a Ledger hardware wallet +- query and execute methods on Nym's smart contracts diff --git a/sdk/typescript/docs/pages/sdk/tsdoc/_meta.json b/sdk/typescript/docs/pages/sdk/tsdoc/_meta.json new file mode 100644 index 0000000000..2a80340c0e --- /dev/null +++ b/sdk/typescript/docs/pages/sdk/tsdoc/_meta.json @@ -0,0 +1,21 @@ +{ + "index": "List of packages", + "@nymproject/sdk": { + "title": "@nymproject/sdk", + "type": "page", + "href": "/docs/tsdoc/nymproject/sdk/", + "newWindow": true + }, + "nymproject/mix-fetch": { + "title": "@nymproject/mix-fetch", + "type": "page", + "href": "/docs/tsdoc/nymproject/mix-fetch/", + "newWindow": true + }, + "nymproject/node-tester": { + "title": "@nymproject/node-tester", + "type": "page", + "href": "/docs/tsdoc/nymproject/node-tester/", + "newWindow": true + } +} diff --git a/sdk/typescript/docs/pages/sdk/tsdoc/index.mdx b/sdk/typescript/docs/pages/sdk/tsdoc/index.mdx new file mode 100644 index 0000000000..632c593e86 --- /dev/null +++ b/sdk/typescript/docs/pages/sdk/tsdoc/index.mdx @@ -0,0 +1,4 @@ +# `tsdoc` for all classes and interfaces + +Nostrud sint occaecat dolore qui mollit deserunt aliquip est elit. Fugiat id minim minim ut incididunt enim ipsum eiusmod tempor pariatur laborum proident. Exercitation adipisicing laborum culpa ipsum irure. Lorem amet anim pariatur exercitation dolore velit. Voluptate tempor proident laboris qui aliqua reprehenderit deserunt. In tempor eu nostrud ex consectetur incididunt in. + diff --git a/sdk/typescript/docs/pnpm-lock.yaml b/sdk/typescript/docs/pnpm-lock.yaml new file mode 100644 index 0000000000..afa36b4e63 --- /dev/null +++ b/sdk/typescript/docs/pnpm-lock.yaml @@ -0,0 +1,2172 @@ +lockfileVersion: 5.3 + +specifiers: + '@types/node': 18.11.10 + next: ^13.0.6 + nextra: latest + nextra-theme-docs: latest + react: ^18.2.0 + react-dom: ^18.2.0 + typescript: ^4.9.3 + +dependencies: + next: 13.0.6_react-dom@18.2.0+react@18.2.0 + nextra: 2.2.14_f26ff3bd08f1cd28b0f73422c76f5ffd + nextra-theme-docs: 2.2.14_d8d66b9d2170cddb63c39dddec8541b9 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + +devDependencies: + '@types/node': 18.11.10 + typescript: 4.9.3 + +packages: + + /@babel/runtime/7.20.6: + resolution: {integrity: sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + dev: false + + /@headlessui/react/1.7.10_react-dom@18.2.0+react@18.2.0: + resolution: {integrity: sha512-1m66h/5eayTEZVT2PI13/2PG3EVC7a9XalmUtVSC8X76pcyKYMuyX1XAL2RUtCr8WhoMa/KrDEyoeU5v+kSQOw==} + engines: {node: '>=10'} + peerDependencies: + react: ^16 || ^17 || ^18 + react-dom: ^16 || ^17 || ^18 + dependencies: + client-only: 0.0.1 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: false + + /@mdx-js/mdx/2.2.1: + resolution: {integrity: sha512-hZ3ex7exYLJn6FfReq8yTvA6TE53uW9UHJQM9IlSauOuS55J9y8RtA7W+dzp6Yrzr00/U1sd7q+Wf61q6SfiTQ==} + dependencies: + '@types/estree-jsx': 1.0.0 + '@types/mdx': 2.0.3 + estree-util-build-jsx: 2.2.0 + estree-util-is-identifier-name: 2.0.1 + estree-util-to-js: 1.1.0 + estree-walker: 3.0.1 + hast-util-to-estree: 2.1.0 + markdown-extensions: 1.1.1 + periscopic: 3.0.4 + remark-mdx: 2.1.5 + remark-parse: 10.0.1 + remark-rehype: 10.1.0 + unified: 10.1.2 + unist-util-position-from-estree: 1.1.1 + unist-util-stringify-position: 3.0.2 + unist-util-visit: 4.1.1 + vfile: 5.3.6 + transitivePeerDependencies: + - supports-color + dev: false + + /@mdx-js/react/2.2.1_react@18.2.0: + resolution: {integrity: sha512-YdXcMcEnqZhzql98RNrqYo9cEhTTesBiCclEtoiQUbJwx87q9453GTapYU6kJ8ZZ2ek1Vp25SiAXEFy5O/eAPw==} + peerDependencies: + react: '>=16' + dependencies: + '@types/mdx': 2.0.3 + '@types/react': 18.0.25 + react: 18.2.0 + dev: false + + /@napi-rs/simple-git-android-arm-eabi/0.1.8: + resolution: {integrity: sha512-JJCejHBB1G6O8nxjQLT4quWCcvLpC3oRdJJ9G3MFYSCoYS8i1bWCWeU+K7Br+xT+D6s1t9q8kNJAwJv9Ygpi0g==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/simple-git-android-arm64/0.1.8: + resolution: {integrity: sha512-mraHzwWBw3tdRetNOS5KnFSjvdAbNBnjFLA8I4PwTCPJj3Q4txrigcPp2d59cJ0TC51xpnPXnZjYdNwwSI9g6g==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/simple-git-darwin-arm64/0.1.8: + resolution: {integrity: sha512-ufy/36eI/j4UskEuvqSH7uXtp3oXeLDmjQCfKJz3u5Vx98KmOMKrqAm2H81AB2WOtCo5mqS6PbBeUXR8BJX8lQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/simple-git-darwin-x64/0.1.8: + resolution: {integrity: sha512-Vb21U+v3tPJNl+8JtIHHT8HGe6WZ8o1Tq3f6p+Jx9Cz71zEbcIiB9FCEMY1knS/jwQEOuhhlI9Qk7d4HY+rprA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/simple-git-linux-arm-gnueabihf/0.1.8: + resolution: {integrity: sha512-6BPTJ7CzpSm2t54mRLVaUr3S7ORJfVJoCk2rQ8v8oDg0XAMKvmQQxOsAgqKBo9gYNHJnqrOx3AEuEgvB586BuQ==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/simple-git-linux-arm64-gnu/0.1.8: + resolution: {integrity: sha512-qfESqUCAA/XoQpRXHptSQ8gIFnETCQt1zY9VOkplx6tgYk9PCeaX4B1Xuzrh3eZamSCMJFn+1YB9Ut8NwyGgAA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/simple-git-linux-arm64-musl/0.1.8: + resolution: {integrity: sha512-G80BQPpaRmQpn8dJGHp4I2/YVhWDUNJwcCrJAtAdbKFDCMyCHJBln2ERL/+IEUlIAT05zK/c1Z5WEprvXEdXow==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/simple-git-linux-x64-gnu/0.1.8: + resolution: {integrity: sha512-NI6o1sZYEf6vPtNWJAm9w8BxJt+LlSFW0liSjYe3lc3e4dhMfV240f0ALeqlwdIldRPaDFwZSJX5/QbS7nMzhw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/simple-git-linux-x64-musl/0.1.8: + resolution: {integrity: sha512-wljGAEOW41er45VTiU8kXJmO480pQKzsgRCvPlJJSCaEVBbmo6XXbFIXnZy1a2J3Zyy2IOsRB4PVkUZaNuPkZQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/simple-git-win32-arm64-msvc/0.1.8: + resolution: {integrity: sha512-QuV4QILyKPfbWHoQKrhXqjiCClx0SxbCTVogkR89BwivekqJMd9UlMxZdoCmwLWutRx4z9KmzQqokvYI5QeepA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/simple-git-win32-x64-msvc/0.1.8: + resolution: {integrity: sha512-UzNS4JtjhZhZ5hRLq7BIUq+4JOwt1ThIKv11CsF1ag2l99f0123XvfEpjczKTaa94nHtjXYc2Mv9TjccBqYOew==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@napi-rs/simple-git/0.1.8: + resolution: {integrity: sha512-BvOMdkkofTz6lEE35itJ/laUokPhr/5ToMGlOH25YnhLD2yN1KpRAT4blW9tT8281/1aZjW3xyi73bs//IrDKA==} + engines: {node: '>= 10'} + optionalDependencies: + '@napi-rs/simple-git-android-arm-eabi': 0.1.8 + '@napi-rs/simple-git-android-arm64': 0.1.8 + '@napi-rs/simple-git-darwin-arm64': 0.1.8 + '@napi-rs/simple-git-darwin-x64': 0.1.8 + '@napi-rs/simple-git-linux-arm-gnueabihf': 0.1.8 + '@napi-rs/simple-git-linux-arm64-gnu': 0.1.8 + '@napi-rs/simple-git-linux-arm64-musl': 0.1.8 + '@napi-rs/simple-git-linux-x64-gnu': 0.1.8 + '@napi-rs/simple-git-linux-x64-musl': 0.1.8 + '@napi-rs/simple-git-win32-arm64-msvc': 0.1.8 + '@napi-rs/simple-git-win32-x64-msvc': 0.1.8 + dev: false + + /@next/env/13.0.6: + resolution: {integrity: sha512-yceT6DCHKqPRS1cAm8DHvDvK74DLIkDQdm5iV+GnIts8h0QbdHvkUIkdOvQoOODgpr6018skbmSQp12z5OWIQQ==} + dev: false + + /@next/swc-android-arm-eabi/13.0.6: + resolution: {integrity: sha512-FGFSj3v2Bluw8fD/X+1eXIEB0PhoJE0zfutsAauRhmNpjjZshLDgoXMWm1jTRL/04K/o9gwwO2+A8+sPVCH1uw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@next/swc-android-arm64/13.0.6: + resolution: {integrity: sha512-7MgbtU7kimxuovVsd7jSJWMkIHBDBUsNLmmlkrBRHTvgzx5nDBXogP0hzZm7EImdOPwVMPpUHRQMBP9mbsiJYQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@next/swc-darwin-arm64/13.0.6: + resolution: {integrity: sha512-AUVEpVTxbP/fxdFsjVI9d5a0CFn6NVV7A/RXOb0Y+pXKIIZ1V5rFjPwpYfIfyOo2lrqgehMNQcyMRoTrhq04xg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@next/swc-darwin-x64/13.0.6: + resolution: {integrity: sha512-SasCDJlshglsPnbzhWaIF6VEGkQy2NECcAOxPwaPr0cwbbt4aUlZ7QmskNzgolr5eAjFS/xTr7CEeKJtZpAAtQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@next/swc-freebsd-x64/13.0.6: + resolution: {integrity: sha512-6Lbxd9gAdXneTkwHyYW/qtX1Tdw7ND9UbiGsGz/SP43ZInNWnW6q0au4hEVPZ9bOWWRKzcVoeTBdoMpQk9Hx9w==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-arm-gnueabihf/13.0.6: + resolution: {integrity: sha512-wNdi5A519e1P+ozEuYOhWPzzE6m1y7mkO6NFwn6watUwO0X9nZs7fT9THmnekvmFQpaZ6U+xf2MQ9poQoCh6jQ==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-arm64-gnu/13.0.6: + resolution: {integrity: sha512-e8KTRnleQY1KLk5PwGV5hrmvKksCc74QRpHl5ffWnEEAtL2FE0ave5aIkXqErsPdXkiKuA/owp3LjQrP+/AH7Q==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-arm64-musl/13.0.6: + resolution: {integrity: sha512-/7RF03C3mhjYpHN+pqOolgME3guiHU5T3TsejuyteqyEyzdEyLHod+jcYH6ft7UZ71a6TdOewvmbLOtzHW2O8A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-x64-gnu/13.0.6: + resolution: {integrity: sha512-kxyEXnYHpOEkFnmrlwB1QlzJtjC6sAJytKcceIyFUHbCaD3W/Qb5tnclcnHKTaFccizZRePXvV25Ok/eUSpKTw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-linux-x64-musl/13.0.6: + resolution: {integrity: sha512-N0c6gubS3WW1oYYgo02xzZnNatfVQP/CiJq2ax+DJ55ePV62IACbRCU99TZNXXg+Kos6vNW4k+/qgvkvpGDeyA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@next/swc-win32-arm64-msvc/13.0.6: + resolution: {integrity: sha512-QjeMB2EBqBFPb/ac0CYr7GytbhUkrG4EwFWbcE0vsRp4H8grt25kYpFQckL4Jak3SUrp7vKfDwZ/SwO7QdO8vw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@next/swc-win32-ia32-msvc/13.0.6: + resolution: {integrity: sha512-EQzXtdqRTcmhT/tCq81rIwE36Y3fNHPInaCuJzM/kftdXfa0F+64y7FAoMO13npX8EG1+SamXgp/emSusKrCXg==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@next/swc-win32-x64-msvc/13.0.6: + resolution: {integrity: sha512-pSkqZ//UP/f2sS9T7IvHLfEWDPTX0vRyXJnAUNisKvO3eF3e1xdhDX7dix/X3Z3lnN4UjSwOzclAI87JFbOwmQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@popperjs/core/2.11.6: + resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==} + dev: false + + /@swc/helpers/0.4.14: + resolution: {integrity: sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==} + dependencies: + tslib: 2.4.1 + dev: false + + /@types/acorn/4.0.6: + resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} + dependencies: + '@types/estree': 1.0.0 + dev: false + + /@types/debug/4.1.7: + resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} + dependencies: + '@types/ms': 0.7.31 + dev: false + + /@types/estree-jsx/1.0.0: + resolution: {integrity: sha512-3qvGd0z8F2ENTGr/GG1yViqfiKmRfrXVx5sJyHGFu3z7m5g5utCQtGp/g29JnjflhtQJBv1WDQukHiT58xPcYQ==} + dependencies: + '@types/estree': 1.0.0 + dev: false + + /@types/estree/1.0.0: + resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} + dev: false + + /@types/hast/2.3.4: + resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /@types/js-yaml/4.0.5: + resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} + dev: false + + /@types/katex/0.11.1: + resolution: {integrity: sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg==} + dev: false + + /@types/mdast/3.0.10: + resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /@types/mdx/2.0.3: + resolution: {integrity: sha512-IgHxcT3RC8LzFLhKwP3gbMPeaK7BM9eBH46OdapPA7yvuIUJ8H6zHZV53J8hGZcTSnt95jANt+rTBNUUc22ACQ==} + dev: false + + /@types/ms/0.7.31: + resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} + dev: false + + /@types/node/18.11.10: + resolution: {integrity: sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==} + dev: true + + /@types/prop-types/15.7.5: + resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} + dev: false + + /@types/react/18.0.25: + resolution: {integrity: sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g==} + dependencies: + '@types/prop-types': 15.7.5 + '@types/scheduler': 0.16.2 + csstype: 3.1.1 + dev: false + + /@types/scheduler/0.16.2: + resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} + dev: false + + /@types/unist/2.0.6: + resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} + dev: false + + /acorn-jsx/5.3.2_acorn@8.8.1: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.8.1 + dev: false + + /acorn/8.8.1: + resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: false + + /ansi-styles/3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: false + + /arch/2.2.0: + resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + dev: false + + /arg/1.0.0: + resolution: {integrity: sha512-Wk7TEzl1KqvTGs/uyhmHO/3XLd3t1UeU4IstvPXVzGPM522cTjqjNZ99esCkcL52sjqjo8e8CTBcWhkxvGzoAw==} + dev: false + + /argparse/1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: false + + /argparse/2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: false + + /astring/1.8.3: + resolution: {integrity: sha512-sRpyiNrx2dEYIMmUXprS8nlpRg2Drs8m9ElX9vVEXaCB4XEAJhKfs7IcX0IwShjuOAjLR6wzIrgoptz1n19i1A==} + hasBin: true + dev: false + + /bail/2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + dev: false + + /caniuse-lite/1.0.30001435: + resolution: {integrity: sha512-kdCkUTjR+v4YAJelyiDTqiu82BDr4W4CP5sgTA0ZBmqn30XfS2ZghPLMowik9TPhS+psWJiUNxsqLyurDbmutA==} + dev: false + + /ccount/2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + dev: false + + /chalk/2.3.0: + resolution: {integrity: sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 4.5.0 + dev: false + + /character-entities-html4/2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + dev: false + + /character-entities-legacy/3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + dev: false + + /character-entities/2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + dev: false + + /character-reference-invalid/2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + dev: false + + /client-only/0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + dev: false + + /clipboardy/1.2.2: + resolution: {integrity: sha512-16KrBOV7bHmHdxcQiCvfUFYVFyEah4FI8vYT1Fr7CGSA4G+xBWMEfUEQJS1hxeHGtI9ju1Bzs9uXSbj5HZKArw==} + engines: {node: '>=4'} + dependencies: + arch: 2.2.0 + execa: 0.8.0 + dev: false + + /clsx/1.2.1: + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} + dev: false + + /color-convert/1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: false + + /color-name/1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: false + + /comma-separated-tokens/2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + dev: false + + /commander/8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + dev: false + + /compute-scroll-into-view/2.0.4: + resolution: {integrity: sha512-y/ZA3BGnxoM/QHHQ2Uy49CLtnWPbt4tTPpEEZiEmmiWBFKjej7nEyH8Ryz54jH0MLXflUYA3Er2zUxPSJu5R+g==} + dev: false + + /cross-spawn/5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + dependencies: + lru-cache: 4.1.5 + shebang-command: 1.2.0 + which: 1.3.1 + dev: false + + /csstype/3.1.1: + resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} + dev: false + + /debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: false + + /decode-named-character-reference/1.0.2: + resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + dependencies: + character-entities: 2.0.2 + dev: false + + /dequal/2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: false + + /diff/5.1.0: + resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} + engines: {node: '>=0.3.1'} + dev: false + + /escape-string-regexp/1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: false + + /escape-string-regexp/5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: false + + /esprima/4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /estree-util-attach-comments/2.1.0: + resolution: {integrity: sha512-rJz6I4L0GaXYtHpoMScgDIwM0/Vwbu5shbMeER596rB2D1EWF6+Gj0e0UKzJPZrpoOc87+Q2kgVFHfjAymIqmw==} + dependencies: + '@types/estree': 1.0.0 + dev: false + + /estree-util-build-jsx/2.2.0: + resolution: {integrity: sha512-apsfRxF9uLrqosApvHVtYZjISPvTJ+lBiIydpC+9wE6cF6ssbhnjyQLqaIjgzGxvC2Hbmec1M7g91PoBayYoQQ==} + dependencies: + '@types/estree-jsx': 1.0.0 + estree-util-is-identifier-name: 2.0.1 + estree-walker: 3.0.1 + dev: false + + /estree-util-is-identifier-name/2.0.1: + resolution: {integrity: sha512-rxZj1GkQhY4x1j/CSnybK9cGuMFQYFPLq0iNyopqf14aOVLFtMv7Esika+ObJWPWiOHuMOAHz3YkWoLYYRnzWQ==} + dev: false + + /estree-util-to-js/1.1.0: + resolution: {integrity: sha512-490lbfCcpLk+ofK6HCgqDfYs4KAfq6QVvDw3+Bm1YoKRgiOjKiKYGAVQE1uwh7zVxBgWhqp4FDtp5SqunpUk1A==} + dependencies: + '@types/estree-jsx': 1.0.0 + astring: 1.8.3 + source-map: 0.7.4 + dev: false + + /estree-util-value-to-estree/1.3.0: + resolution: {integrity: sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw==} + engines: {node: '>=12.0.0'} + dependencies: + is-plain-obj: 3.0.0 + dev: false + + /estree-util-visit/1.2.0: + resolution: {integrity: sha512-wdsoqhWueuJKsh5hqLw3j8lwFqNStm92VcwtAOAny8g/KS/l5Y8RISjR4k5W6skCj3Nirag/WUCMS0Nfy3sgsg==} + dependencies: + '@types/estree-jsx': 1.0.0 + '@types/unist': 2.0.6 + dev: false + + /estree-walker/3.0.1: + resolution: {integrity: sha512-woY0RUD87WzMBUiZLx8NsYr23N5BKsOMZHhu2hoNRVh6NXGfoiT1KOL8G3UHlJAnEDGmfa5ubNA/AacfG+Kb0g==} + dev: false + + /execa/0.8.0: + resolution: {integrity: sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==} + engines: {node: '>=4'} + dependencies: + cross-spawn: 5.1.0 + get-stream: 3.0.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.7 + strip-eof: 1.0.0 + dev: false + + /extend-shallow/2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: false + + /extend/3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: false + + /flexsearch/0.7.31: + resolution: {integrity: sha512-XGozTsMPYkm+6b5QL3Z9wQcJjNYxp0CYn3U1gO7dwD6PAqU1SVWZxI9CCg3z+ml3YfqdPnrBehaBrnH2AGKbNA==} + dev: false + + /focus-visible/5.2.0: + resolution: {integrity: sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==} + dev: false + + /get-stream/3.0.0: + resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} + engines: {node: '>=4'} + dev: false + + /git-up/7.0.0: + resolution: {integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==} + dependencies: + is-ssh: 1.4.0 + parse-url: 8.1.0 + dev: false + + /git-url-parse/13.1.0: + resolution: {integrity: sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==} + dependencies: + git-up: 7.0.0 + dev: false + + /github-slugger/2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + dev: false + + /graceful-fs/4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + dev: false + + /gray-matter/4.0.3: + resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} + engines: {node: '>=6.0'} + dependencies: + js-yaml: 3.14.1 + kind-of: 6.0.3 + section-matter: 1.0.0 + strip-bom-string: 1.0.0 + dev: false + + /has-flag/2.0.0: + resolution: {integrity: sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==} + engines: {node: '>=0.10.0'} + dev: false + + /hash-obj/4.0.0: + resolution: {integrity: sha512-FwO1BUVWkyHasWDW4S8o0ssQXjvyghLV2rfVhnN36b2bbcj45eGiuzdn9XOvOpjV3TKQD7Gm2BWNXdE9V4KKYg==} + engines: {node: '>=12'} + dependencies: + is-obj: 3.0.0 + sort-keys: 5.0.0 + type-fest: 1.4.0 + dev: false + + /hast-util-from-parse5/7.1.1: + resolution: {integrity: sha512-R6PoNcUs89ZxLJmMWsVbwSWuz95/9OriyQZ3e2ybwqGsRXzhA6gv49rgGmQvLbZuSNDv9fCg7vV7gXUsvtUFaA==} + dependencies: + '@types/hast': 2.3.4 + '@types/unist': 2.0.6 + hastscript: 7.2.0 + property-information: 6.2.0 + vfile: 5.3.6 + vfile-location: 4.0.1 + web-namespaces: 2.0.1 + dev: false + + /hast-util-is-element/2.1.3: + resolution: {integrity: sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA==} + dependencies: + '@types/hast': 2.3.4 + '@types/unist': 2.0.6 + dev: false + + /hast-util-parse-selector/3.1.1: + resolution: {integrity: sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==} + dependencies: + '@types/hast': 2.3.4 + dev: false + + /hast-util-to-estree/2.1.0: + resolution: {integrity: sha512-Vwch1etMRmm89xGgz+voWXvVHba2iiMdGMKmaMfYt35rbVtFDq8JNwwAIvi8zHMkO6Gvqo9oTMwJTmzVRfXh4g==} + dependencies: + '@types/estree': 1.0.0 + '@types/estree-jsx': 1.0.0 + '@types/hast': 2.3.4 + '@types/unist': 2.0.6 + comma-separated-tokens: 2.0.3 + estree-util-attach-comments: 2.1.0 + estree-util-is-identifier-name: 2.0.1 + hast-util-whitespace: 2.0.0 + mdast-util-mdx-expression: 1.3.1 + mdast-util-mdxjs-esm: 1.3.0 + property-information: 6.2.0 + space-separated-tokens: 2.0.2 + style-to-object: 0.3.0 + unist-util-position: 4.0.3 + zwitch: 2.0.4 + transitivePeerDependencies: + - supports-color + dev: false + + /hast-util-to-text/3.1.2: + resolution: {integrity: sha512-tcllLfp23dJJ+ju5wCCZHVpzsQQ43+moJbqVX3jNWPB7z/KFC4FyZD6R7y94cHL6MQ33YtMZL8Z0aIXXI4XFTw==} + dependencies: + '@types/hast': 2.3.4 + '@types/unist': 2.0.6 + hast-util-is-element: 2.1.3 + unist-util-find-after: 4.0.1 + dev: false + + /hast-util-whitespace/2.0.0: + resolution: {integrity: sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg==} + dev: false + + /hastscript/7.2.0: + resolution: {integrity: sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==} + dependencies: + '@types/hast': 2.3.4 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 3.1.1 + property-information: 6.2.0 + space-separated-tokens: 2.0.2 + dev: false + + /inline-style-parser/0.1.1: + resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} + dev: false + + /intersection-observer/0.12.2: + resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} + dev: false + + /is-alphabetical/2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + dev: false + + /is-alphanumerical/2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + dev: false + + /is-buffer/2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + dev: false + + /is-decimal/2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + dev: false + + /is-extendable/0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: false + + /is-hexadecimal/2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + dev: false + + /is-obj/3.0.0: + resolution: {integrity: sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==} + engines: {node: '>=12'} + dev: false + + /is-plain-obj/3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + dev: false + + /is-plain-obj/4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + dev: false + + /is-reference/3.0.0: + resolution: {integrity: sha512-Eo1W3wUoHWoCoVM4GVl/a+K0IgiqE5aIo4kJABFyMum1ZORlPkC+UC357sSQUL5w5QCE5kCC9upl75b7+7CY/Q==} + dependencies: + '@types/estree': 1.0.0 + dev: false + + /is-ssh/1.4.0: + resolution: {integrity: sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==} + dependencies: + protocols: 2.0.1 + dev: false + + /is-stream/1.1.0: + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} + dev: false + + /isexe/2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: false + + /js-tokens/4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: false + + /js-yaml/3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: false + + /js-yaml/4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: false + + /jsonc-parser/3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + dev: false + + /katex/0.13.24: + resolution: {integrity: sha512-jZxYuKCma3VS5UuxOx/rFV1QyGSl3Uy/i0kTJF3HgQ5xMinCQVF8Zd4bMY/9aI9b9A2pjIBOsjSSm68ykTAr8w==} + hasBin: true + dependencies: + commander: 8.3.0 + dev: false + + /katex/0.15.6: + resolution: {integrity: sha512-UpzJy4yrnqnhXvRPhjEuLA4lcPn6eRngixW7Q3TJErjg3Aw2PuLFBzTkdUb89UtumxjhHTqL3a5GDGETMSwgJA==} + hasBin: true + dependencies: + commander: 8.3.0 + dev: false + + /katex/0.16.4: + resolution: {integrity: sha512-WudRKUj8yyBeVDI4aYMNxhx5Vhh2PjpzQw1GRu/LVGqL4m1AxwD1GcUp0IMbdJaf5zsjtj8ghP0DOQRYhroNkw==} + hasBin: true + dependencies: + commander: 8.3.0 + dev: false + + /kind-of/6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: false + + /kleur/4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + dev: false + + /lodash.get/4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + dev: false + + /longest-streak/3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + dev: false + + /loose-envify/1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + dev: false + + /lru-cache/4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + dependencies: + pseudomap: 1.0.2 + yallist: 2.1.2 + dev: false + + /markdown-extensions/1.1.1: + resolution: {integrity: sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==} + engines: {node: '>=0.10.0'} + dev: false + + /markdown-table/3.0.3: + resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + dev: false + + /match-sorter/6.3.1: + resolution: {integrity: sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==} + dependencies: + '@babel/runtime': 7.20.6 + remove-accents: 0.4.2 + dev: false + + /mdast-util-definitions/5.1.1: + resolution: {integrity: sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ==} + dependencies: + '@types/mdast': 3.0.10 + '@types/unist': 2.0.6 + unist-util-visit: 4.1.1 + dev: false + + /mdast-util-find-and-replace/2.2.1: + resolution: {integrity: sha512-SobxkQXFAdd4b5WmEakmkVoh18icjQRxGy5OWTCzgsLRm1Fu/KCtwD1HIQSsmq5ZRjVH0Ehwg6/Fn3xIUk+nKw==} + dependencies: + escape-string-regexp: 5.0.0 + unist-util-is: 5.1.1 + unist-util-visit-parents: 5.1.1 + dev: false + + /mdast-util-from-markdown/1.2.0: + resolution: {integrity: sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q==} + dependencies: + '@types/mdast': 3.0.10 + '@types/unist': 2.0.6 + decode-named-character-reference: 1.0.2 + mdast-util-to-string: 3.1.0 + micromark: 3.1.0 + micromark-util-decode-numeric-character-reference: 1.0.0 + micromark-util-decode-string: 1.0.2 + micromark-util-normalize-identifier: 1.0.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + unist-util-stringify-position: 3.0.2 + uvu: 0.5.6 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-autolink-literal/1.0.2: + resolution: {integrity: sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg==} + dependencies: + '@types/mdast': 3.0.10 + ccount: 2.0.1 + mdast-util-find-and-replace: 2.2.1 + micromark-util-character: 1.1.0 + dev: false + + /mdast-util-gfm-footnote/1.0.1: + resolution: {integrity: sha512-p+PrYlkw9DeCRkTVw1duWqPRHX6Ywh2BNKJQcZbCwAuP/59B0Lk9kakuAd7KbQprVO4GzdW8eS5++A9PUSqIyw==} + dependencies: + '@types/mdast': 3.0.10 + mdast-util-to-markdown: 1.3.0 + micromark-util-normalize-identifier: 1.0.0 + dev: false + + /mdast-util-gfm-strikethrough/1.0.2: + resolution: {integrity: sha512-T/4DVHXcujH6jx1yqpcAYYwd+z5lAYMw4Ls6yhTfbMMtCt0PHY4gEfhW9+lKsLBtyhUGKRIzcUA2FATVqnvPDA==} + dependencies: + '@types/mdast': 3.0.10 + mdast-util-to-markdown: 1.3.0 + dev: false + + /mdast-util-gfm-table/1.0.6: + resolution: {integrity: sha512-uHR+fqFq3IvB3Rd4+kzXW8dmpxUhvgCQZep6KdjsLK4O6meK5dYZEayLtIxNus1XO3gfjfcIFe8a7L0HZRGgag==} + dependencies: + '@types/mdast': 3.0.10 + markdown-table: 3.0.3 + mdast-util-from-markdown: 1.2.0 + mdast-util-to-markdown: 1.3.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-task-list-item/1.0.1: + resolution: {integrity: sha512-KZ4KLmPdABXOsfnM6JHUIjxEvcx2ulk656Z/4Balw071/5qgnhz+H1uGtf2zIGnrnvDC8xR4Fj9uKbjAFGNIeA==} + dependencies: + '@types/mdast': 3.0.10 + mdast-util-to-markdown: 1.3.0 + dev: false + + /mdast-util-gfm/2.0.1: + resolution: {integrity: sha512-42yHBbfWIFisaAfV1eixlabbsa6q7vHeSPY+cg+BBjX51M8xhgMacqH9g6TftB/9+YkcI0ooV4ncfrJslzm/RQ==} + dependencies: + mdast-util-from-markdown: 1.2.0 + mdast-util-gfm-autolink-literal: 1.0.2 + mdast-util-gfm-footnote: 1.0.1 + mdast-util-gfm-strikethrough: 1.0.2 + mdast-util-gfm-table: 1.0.6 + mdast-util-gfm-task-list-item: 1.0.1 + mdast-util-to-markdown: 1.3.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-math/2.0.2: + resolution: {integrity: sha512-8gmkKVp9v6+Tgjtq6SYx9kGPpTf6FVYRa53/DLh479aldR9AyP48qeVOgNZ5X7QUK7nOy4yw7vg6mbiGcs9jWQ==} + dependencies: + '@types/mdast': 3.0.10 + longest-streak: 3.1.0 + mdast-util-to-markdown: 1.3.0 + dev: false + + /mdast-util-mdx-expression/1.3.1: + resolution: {integrity: sha512-TTb6cKyTA1RD+1su1iStZ5PAv3rFfOUKcoU5EstUpv/IZo63uDX03R8+jXjMEhcobXnNOiG6/ccekvVl4eV1zQ==} + dependencies: + '@types/estree-jsx': 1.0.0 + '@types/hast': 2.3.4 + '@types/mdast': 3.0.10 + mdast-util-from-markdown: 1.2.0 + mdast-util-to-markdown: 1.3.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-mdx-jsx/2.1.0: + resolution: {integrity: sha512-KzgzfWMhdteDkrY4mQtyvTU5bc/W4ppxhe9SzelO6QUUiwLAM+Et2Dnjjprik74a336kHdo0zKm7Tp+n6FFeRg==} + dependencies: + '@types/estree-jsx': 1.0.0 + '@types/hast': 2.3.4 + '@types/mdast': 3.0.10 + ccount: 2.0.1 + mdast-util-to-markdown: 1.3.0 + parse-entities: 4.0.0 + stringify-entities: 4.0.3 + unist-util-remove-position: 4.0.1 + unist-util-stringify-position: 3.0.2 + vfile-message: 3.1.3 + dev: false + + /mdast-util-mdx/2.0.0: + resolution: {integrity: sha512-M09lW0CcBT1VrJUaF/PYxemxxHa7SLDHdSn94Q9FhxjCQfuW7nMAWKWimTmA3OyDMSTH981NN1csW1X+HPSluw==} + dependencies: + mdast-util-mdx-expression: 1.3.1 + mdast-util-mdx-jsx: 2.1.0 + mdast-util-mdxjs-esm: 1.3.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-mdxjs-esm/1.3.0: + resolution: {integrity: sha512-7N5ihsOkAEGjFotIX9p/YPdl4TqUoMxL4ajNz7PbT89BqsdWJuBC9rvgt6wpbwTZqWWR0jKWqQbwsOWDBUZv4g==} + dependencies: + '@types/estree-jsx': 1.0.0 + '@types/hast': 2.3.4 + '@types/mdast': 3.0.10 + mdast-util-from-markdown: 1.2.0 + mdast-util-to-markdown: 1.3.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-to-hast/12.2.4: + resolution: {integrity: sha512-a21xoxSef1l8VhHxS1Dnyioz6grrJkoaCUgGzMD/7dWHvboYX3VW53esRUfB5tgTyz4Yos1n25SPcj35dJqmAg==} + dependencies: + '@types/hast': 2.3.4 + '@types/mdast': 3.0.10 + mdast-util-definitions: 5.1.1 + micromark-util-sanitize-uri: 1.1.0 + trim-lines: 3.0.1 + unist-builder: 3.0.0 + unist-util-generated: 2.0.0 + unist-util-position: 4.0.3 + unist-util-visit: 4.1.1 + dev: false + + /mdast-util-to-markdown/1.3.0: + resolution: {integrity: sha512-6tUSs4r+KK4JGTTiQ7FfHmVOaDrLQJPmpjD6wPMlHGUVXoG9Vjc3jIeP+uyBWRf8clwB2blM+W7+KrlMYQnftA==} + dependencies: + '@types/mdast': 3.0.10 + '@types/unist': 2.0.6 + longest-streak: 3.1.0 + mdast-util-to-string: 3.1.0 + micromark-util-decode-string: 1.0.2 + unist-util-visit: 4.1.1 + zwitch: 2.0.4 + dev: false + + /mdast-util-to-string/3.1.0: + resolution: {integrity: sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==} + dev: false + + /micromark-core-commonmark/1.0.6: + resolution: {integrity: sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA==} + dependencies: + decode-named-character-reference: 1.0.2 + micromark-factory-destination: 1.0.0 + micromark-factory-label: 1.0.2 + micromark-factory-space: 1.0.0 + micromark-factory-title: 1.0.2 + micromark-factory-whitespace: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-chunked: 1.0.0 + micromark-util-classify-character: 1.0.0 + micromark-util-html-tag-name: 1.1.0 + micromark-util-normalize-identifier: 1.0.0 + micromark-util-resolve-all: 1.0.0 + micromark-util-subtokenize: 1.0.2 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm-autolink-literal/1.0.3: + resolution: {integrity: sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-sanitize-uri: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm-footnote/1.0.4: + resolution: {integrity: sha512-E/fmPmDqLiMUP8mLJ8NbJWJ4bTw6tS+FEQS8CcuDtZpILuOb2kjLqPEeAePF1djXROHXChM/wPJw0iS4kHCcIg==} + dependencies: + micromark-core-commonmark: 1.0.6 + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-normalize-identifier: 1.0.0 + micromark-util-sanitize-uri: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm-strikethrough/1.0.4: + resolution: {integrity: sha512-/vjHU/lalmjZCT5xt7CcHVJGq8sYRm80z24qAKXzaHzem/xsDYb2yLL+NNVbYvmpLx3O7SYPuGL5pzusL9CLIQ==} + dependencies: + micromark-util-chunked: 1.0.0 + micromark-util-classify-character: 1.0.0 + micromark-util-resolve-all: 1.0.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm-table/1.0.5: + resolution: {integrity: sha512-xAZ8J1X9W9K3JTJTUL7G6wSKhp2ZYHrFk5qJgY/4B33scJzE2kpfRL6oiw/veJTbt7jiM/1rngLlOKPWr1G+vg==} + dependencies: + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm-tagfilter/1.0.1: + resolution: {integrity: sha512-Ty6psLAcAjboRa/UKUbbUcwjVAv5plxmpUTy2XC/3nJFL37eHej8jrHrRzkqcpipJliuBH30DTs7+3wqNcQUVA==} + dependencies: + micromark-util-types: 1.0.2 + dev: false + + /micromark-extension-gfm-task-list-item/1.0.3: + resolution: {integrity: sha512-PpysK2S1Q/5VXi72IIapbi/jliaiOFzv7THH4amwXeYXLq3l1uo8/2Be0Ac1rEwK20MQEsGH2ltAZLNY2KI/0Q==} + dependencies: + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm/2.0.1: + resolution: {integrity: sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA==} + dependencies: + micromark-extension-gfm-autolink-literal: 1.0.3 + micromark-extension-gfm-footnote: 1.0.4 + micromark-extension-gfm-strikethrough: 1.0.4 + micromark-extension-gfm-table: 1.0.5 + micromark-extension-gfm-tagfilter: 1.0.1 + micromark-extension-gfm-task-list-item: 1.0.3 + micromark-util-combine-extensions: 1.0.0 + micromark-util-types: 1.0.2 + dev: false + + /micromark-extension-math/2.0.2: + resolution: {integrity: sha512-cFv2B/E4pFPBBFuGgLHkkNiFAIQv08iDgPH2HCuR2z3AUgMLecES5Cq7AVtwOtZeRrbA80QgMUk8VVW0Z+D2FA==} + dependencies: + '@types/katex': 0.11.1 + katex: 0.13.24 + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + dev: false + + /micromark-extension-mdx-expression/1.0.3: + resolution: {integrity: sha512-TjYtjEMszWze51NJCZmhv7MEBcgYRgb3tJeMAJ+HQCAaZHHRBaDCccqQzGizR/H4ODefP44wRTgOn2vE5I6nZA==} + dependencies: + micromark-factory-mdx-expression: 1.0.6 + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-events-to-acorn: 1.2.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + dev: false + + /micromark-extension-mdx-jsx/1.0.3: + resolution: {integrity: sha512-VfA369RdqUISF0qGgv2FfV7gGjHDfn9+Qfiv5hEwpyr1xscRj/CiVRkU7rywGFCO7JwJ5L0e7CJz60lY52+qOA==} + dependencies: + '@types/acorn': 4.0.6 + estree-util-is-identifier-name: 2.0.1 + micromark-factory-mdx-expression: 1.0.6 + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + vfile-message: 3.1.3 + dev: false + + /micromark-extension-mdx-md/1.0.0: + resolution: {integrity: sha512-xaRAMoSkKdqZXDAoSgp20Azm0aRQKGOl0RrS81yGu8Hr/JhMsBmfs4wR7m9kgVUIO36cMUQjNyiyDKPrsv8gOw==} + dependencies: + micromark-util-types: 1.0.2 + dev: false + + /micromark-extension-mdxjs-esm/1.0.3: + resolution: {integrity: sha512-2N13ol4KMoxb85rdDwTAC6uzs8lMX0zeqpcyx7FhS7PxXomOnLactu8WI8iBNXW8AVyea3KIJd/1CKnUmwrK9A==} + dependencies: + micromark-core-commonmark: 1.0.6 + micromark-util-character: 1.1.0 + micromark-util-events-to-acorn: 1.2.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + unist-util-position-from-estree: 1.1.1 + uvu: 0.5.6 + vfile-message: 3.1.3 + dev: false + + /micromark-extension-mdxjs/1.0.0: + resolution: {integrity: sha512-TZZRZgeHvtgm+IhtgC2+uDMR7h8eTKF0QUX9YsgoL9+bADBpBY6SiLvWqnBlLbCEevITmTqmEuY3FoxMKVs1rQ==} + dependencies: + acorn: 8.8.1 + acorn-jsx: 5.3.2_acorn@8.8.1 + micromark-extension-mdx-expression: 1.0.3 + micromark-extension-mdx-jsx: 1.0.3 + micromark-extension-mdx-md: 1.0.0 + micromark-extension-mdxjs-esm: 1.0.3 + micromark-util-combine-extensions: 1.0.0 + micromark-util-types: 1.0.2 + dev: false + + /micromark-factory-destination/1.0.0: + resolution: {integrity: sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + dev: false + + /micromark-factory-label/1.0.2: + resolution: {integrity: sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + dev: false + + /micromark-factory-mdx-expression/1.0.6: + resolution: {integrity: sha512-WRQIc78FV7KrCfjsEf/sETopbYjElh3xAmNpLkd1ODPqxEngP42eVRGbiPEQWpRV27LzqW+XVTvQAMIIRLPnNA==} + dependencies: + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-events-to-acorn: 1.2.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + unist-util-position-from-estree: 1.1.1 + uvu: 0.5.6 + vfile-message: 3.1.3 + dev: false + + /micromark-factory-space/1.0.0: + resolution: {integrity: sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-types: 1.0.2 + dev: false + + /micromark-factory-title/1.0.2: + resolution: {integrity: sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==} + dependencies: + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + dev: false + + /micromark-factory-whitespace/1.0.0: + resolution: {integrity: sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==} + dependencies: + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + dev: false + + /micromark-util-character/1.1.0: + resolution: {integrity: sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==} + dependencies: + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + dev: false + + /micromark-util-chunked/1.0.0: + resolution: {integrity: sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==} + dependencies: + micromark-util-symbol: 1.0.1 + dev: false + + /micromark-util-classify-character/1.0.0: + resolution: {integrity: sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + dev: false + + /micromark-util-combine-extensions/1.0.0: + resolution: {integrity: sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==} + dependencies: + micromark-util-chunked: 1.0.0 + micromark-util-types: 1.0.2 + dev: false + + /micromark-util-decode-numeric-character-reference/1.0.0: + resolution: {integrity: sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==} + dependencies: + micromark-util-symbol: 1.0.1 + dev: false + + /micromark-util-decode-string/1.0.2: + resolution: {integrity: sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q==} + dependencies: + decode-named-character-reference: 1.0.2 + micromark-util-character: 1.1.0 + micromark-util-decode-numeric-character-reference: 1.0.0 + micromark-util-symbol: 1.0.1 + dev: false + + /micromark-util-encode/1.0.1: + resolution: {integrity: sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA==} + dev: false + + /micromark-util-events-to-acorn/1.2.0: + resolution: {integrity: sha512-WWp3bf7xT9MppNuw3yPjpnOxa8cj5ACivEzXJKu0WwnjBYfzaBvIAT9KfeyI0Qkll+bfQtfftSwdgTH6QhTOKw==} + dependencies: + '@types/acorn': 4.0.6 + '@types/estree': 1.0.0 + estree-util-visit: 1.2.0 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + vfile-location: 4.0.1 + vfile-message: 3.1.3 + dev: false + + /micromark-util-html-tag-name/1.1.0: + resolution: {integrity: sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA==} + dev: false + + /micromark-util-normalize-identifier/1.0.0: + resolution: {integrity: sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==} + dependencies: + micromark-util-symbol: 1.0.1 + dev: false + + /micromark-util-resolve-all/1.0.0: + resolution: {integrity: sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==} + dependencies: + micromark-util-types: 1.0.2 + dev: false + + /micromark-util-sanitize-uri/1.1.0: + resolution: {integrity: sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-encode: 1.0.1 + micromark-util-symbol: 1.0.1 + dev: false + + /micromark-util-subtokenize/1.0.2: + resolution: {integrity: sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==} + dependencies: + micromark-util-chunked: 1.0.0 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + dev: false + + /micromark-util-symbol/1.0.1: + resolution: {integrity: sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ==} + dev: false + + /micromark-util-types/1.0.2: + resolution: {integrity: sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w==} + dev: false + + /micromark/3.1.0: + resolution: {integrity: sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA==} + dependencies: + '@types/debug': 4.1.7 + debug: 4.3.4 + decode-named-character-reference: 1.0.2 + micromark-core-commonmark: 1.0.6 + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-chunked: 1.0.0 + micromark-util-combine-extensions: 1.0.0 + micromark-util-decode-numeric-character-reference: 1.0.0 + micromark-util-encode: 1.0.1 + micromark-util-normalize-identifier: 1.0.0 + micromark-util-resolve-all: 1.0.0 + micromark-util-sanitize-uri: 1.1.0 + micromark-util-subtokenize: 1.0.2 + micromark-util-symbol: 1.0.1 + micromark-util-types: 1.0.2 + uvu: 0.5.6 + transitivePeerDependencies: + - supports-color + dev: false + + /mri/1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + dev: false + + /ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: false + + /nanoid/3.3.4: + resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: false + + /nanoid/4.0.1: + resolution: {integrity: sha512-udKGtCCUafD3nQtJg9wBhRP3KMbPglUsgV5JVsXhvyBs/oefqb4sqMEhKBBgqZncYowu58p1prsZQBYvAj/Gww==} + engines: {node: ^14 || ^16 || >=18} + hasBin: true + dev: false + + /next-mdx-remote/4.3.0_react-dom@18.2.0+react@18.2.0: + resolution: {integrity: sha512-fbxkY03pM2Wx5bDNTVKpYD5Hx3QVZGH+6xDtVIxlxXz4HTifP1yI2DrkDvxXbTz0SYGIbluRMIW81IOOa8pigA==} + engines: {node: '>=14', npm: '>=7'} + peerDependencies: + react: '>=16.x <=18.x' + react-dom: '>=16.x <=18.x' + dependencies: + '@mdx-js/mdx': 2.2.1 + '@mdx-js/react': 2.2.1_react@18.2.0 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + vfile: 5.3.6 + vfile-matter: 3.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /next-seo/5.14.1_f26ff3bd08f1cd28b0f73422c76f5ffd: + resolution: {integrity: sha512-NiJeQbxYP3z+EMp52q8k3Q+OfX2+Yv2WehERDj98r2wjXxL+woKpRBdsSVYolTD0Hm8IWs42SzaISE93RoQdOw==} + peerDependencies: + next: ^8.1.1-canary.54 || >=9.0.0 + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + next: 13.0.6_react-dom@18.2.0+react@18.2.0 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: false + + /next-themes/0.2.1_f26ff3bd08f1cd28b0f73422c76f5ffd: + resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} + peerDependencies: + next: '*' + react: '*' + react-dom: '*' + dependencies: + next: 13.0.6_react-dom@18.2.0+react@18.2.0 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: false + + /next/13.0.6_react-dom@18.2.0+react@18.2.0: + resolution: {integrity: sha512-COvigvms2LRt1rrzfBQcMQ2GZd86Mvk1z+LOLY5pniFtL4VrTmhZ9salrbKfSiXbhsD01TrDdD68ec3ABDyscA==} + engines: {node: '>=14.6.0'} + hasBin: true + peerDependencies: + fibers: '>= 3.1.0' + node-sass: ^6.0.0 || ^7.0.0 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + peerDependenciesMeta: + fibers: + optional: true + node-sass: + optional: true + sass: + optional: true + dependencies: + '@next/env': 13.0.6 + '@swc/helpers': 0.4.14 + caniuse-lite: 1.0.30001435 + postcss: 8.4.14 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + styled-jsx: 5.1.0_react@18.2.0 + optionalDependencies: + '@next/swc-android-arm-eabi': 13.0.6 + '@next/swc-android-arm64': 13.0.6 + '@next/swc-darwin-arm64': 13.0.6 + '@next/swc-darwin-x64': 13.0.6 + '@next/swc-freebsd-x64': 13.0.6 + '@next/swc-linux-arm-gnueabihf': 13.0.6 + '@next/swc-linux-arm64-gnu': 13.0.6 + '@next/swc-linux-arm64-musl': 13.0.6 + '@next/swc-linux-x64-gnu': 13.0.6 + '@next/swc-linux-x64-musl': 13.0.6 + '@next/swc-win32-arm64-msvc': 13.0.6 + '@next/swc-win32-ia32-msvc': 13.0.6 + '@next/swc-win32-x64-msvc': 13.0.6 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + dev: false + + /nextra-theme-docs/2.2.14_d8d66b9d2170cddb63c39dddec8541b9: + resolution: {integrity: sha512-QQcHOcAXSfrpbSX3FqXgcQ2favKLnBAczqKWbSDVEtgHiUG6s7pVpxclpKm5F1c/fP47v19USRq3BL/SZ4JEIQ==} + peerDependencies: + next: '>=9.5.3' + nextra: 2.2.14 + react: '>=16.13.1' + react-dom: '>=16.13.1' + dependencies: + '@headlessui/react': 1.7.10_react-dom@18.2.0+react@18.2.0 + '@popperjs/core': 2.11.6 + clsx: 1.2.1 + flexsearch: 0.7.31 + focus-visible: 5.2.0 + git-url-parse: 13.1.0 + intersection-observer: 0.12.2 + match-sorter: 6.3.1 + next: 13.0.6_react-dom@18.2.0+react@18.2.0 + next-seo: 5.14.1_f26ff3bd08f1cd28b0f73422c76f5ffd + next-themes: 0.2.1_f26ff3bd08f1cd28b0f73422c76f5ffd + nextra: 2.2.14_f26ff3bd08f1cd28b0f73422c76f5ffd + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + scroll-into-view-if-needed: 3.0.4 + zod: 3.20.2 + dev: false + + /nextra/2.2.14_f26ff3bd08f1cd28b0f73422c76f5ffd: + resolution: {integrity: sha512-kToTiTiE4qrQsQ9snFRqCGLLSjKSFgFV/BJm3yp/SRmkmCr1WaWrlmUTAuXlxM7PREbNaZouNSOJ0hGS92rM8A==} + peerDependencies: + next: '>=9.5.3' + react: '>=16.13.1' + react-dom: '>=16.13.1' + dependencies: + '@mdx-js/mdx': 2.2.1 + '@mdx-js/react': 2.2.1_react@18.2.0 + '@napi-rs/simple-git': 0.1.8 + github-slugger: 2.0.0 + graceful-fs: 4.2.10 + gray-matter: 4.0.3 + katex: 0.16.4 + lodash.get: 4.4.2 + next: 13.0.6_react-dom@18.2.0+react@18.2.0 + next-mdx-remote: 4.3.0_react-dom@18.2.0+react@18.2.0 + p-limit: 3.1.0 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + rehype-katex: 6.0.2 + rehype-pretty-code: 0.9.2_shiki@0.12.1 + remark-gfm: 3.0.1 + remark-math: 5.1.1 + remark-reading-time: 2.0.1 + shiki: 0.12.1 + slash: 3.0.0 + title: 3.5.3 + unist-util-remove: 3.1.1 + unist-util-visit: 4.1.1 + transitivePeerDependencies: + - supports-color + dev: false + + /npm-run-path/2.0.2: + resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} + engines: {node: '>=4'} + dependencies: + path-key: 2.0.1 + dev: false + + /p-finally/1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + dev: false + + /p-limit/3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: false + + /parse-entities/4.0.0: + resolution: {integrity: sha512-5nk9Fn03x3rEhGaX1FU6IDwG/k+GxLXlFAkgrbM1asuAFl3BhdQWvASaIsmwWypRNcZKHPYnIuOSfIWEyEQnPQ==} + dependencies: + '@types/unist': 2.0.6 + character-entities: 2.0.2 + character-entities-legacy: 3.0.0 + character-reference-invalid: 2.0.1 + decode-named-character-reference: 1.0.2 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + is-hexadecimal: 2.0.1 + dev: false + + /parse-numeric-range/1.3.0: + resolution: {integrity: sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==} + dev: false + + /parse-path/7.0.0: + resolution: {integrity: sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==} + dependencies: + protocols: 2.0.1 + dev: false + + /parse-url/8.1.0: + resolution: {integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==} + dependencies: + parse-path: 7.0.0 + dev: false + + /parse5/6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + dev: false + + /path-key/2.0.1: + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + engines: {node: '>=4'} + dev: false + + /periscopic/3.0.4: + resolution: {integrity: sha512-SFx68DxCv0Iyo6APZuw/AKewkkThGwssmU0QWtTlvov3VAtPX+QJ4CadwSaz8nrT5jPIuxdvJWB4PnD2KNDxQg==} + dependencies: + estree-walker: 3.0.1 + is-reference: 3.0.0 + dev: false + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: false + + /postcss/8.4.14: + resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.4 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: false + + /property-information/6.2.0: + resolution: {integrity: sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==} + dev: false + + /protocols/2.0.1: + resolution: {integrity: sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==} + dev: false + + /pseudomap/1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + dev: false + + /react-dom/18.2.0_react@18.2.0: + resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + peerDependencies: + react: ^18.2.0 + dependencies: + loose-envify: 1.4.0 + react: 18.2.0 + scheduler: 0.23.0 + dev: false + + /react/18.2.0: + resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + dev: false + + /reading-time/1.5.0: + resolution: {integrity: sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==} + dev: false + + /regenerator-runtime/0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + dev: false + + /rehype-katex/6.0.2: + resolution: {integrity: sha512-C4gDAlS1+l0hJqctyiU64f9CvT00S03qV1T6HiMzbSuLBgWUtcqydWHY9OpKrm0SpkK16FNd62CDKyWLwV2ppg==} + dependencies: + '@types/hast': 2.3.4 + '@types/katex': 0.11.1 + hast-util-to-text: 3.1.2 + katex: 0.15.6 + rehype-parse: 8.0.4 + unified: 10.1.2 + unist-util-remove-position: 4.0.1 + unist-util-visit: 4.1.1 + dev: false + + /rehype-parse/8.0.4: + resolution: {integrity: sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg==} + dependencies: + '@types/hast': 2.3.4 + hast-util-from-parse5: 7.1.1 + parse5: 6.0.1 + unified: 10.1.2 + dev: false + + /rehype-pretty-code/0.9.2_shiki@0.12.1: + resolution: {integrity: sha512-l369pvBK6ihBEuy2+VDpHU+zbbY8I+Z4LiyIOunHAt3xyw6selaOFKc/DnX94jI5OJb3+NgjbOxXx2yaAypjZw==} + engines: {node: ^12.16.0 || >=13.2.0} + peerDependencies: + shiki: '*' + dependencies: + hash-obj: 4.0.0 + nanoid: 4.0.1 + parse-numeric-range: 1.3.0 + shiki: 0.12.1 + dev: false + + /remark-gfm/3.0.1: + resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==} + dependencies: + '@types/mdast': 3.0.10 + mdast-util-gfm: 2.0.1 + micromark-extension-gfm: 2.0.1 + unified: 10.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-math/5.1.1: + resolution: {integrity: sha512-cE5T2R/xLVtfFI4cCePtiRn+e6jKMtFDR3P8V3qpv8wpKjwvHoBA4eJzvX+nVrnlNy0911bdGmuspCSwetfYHw==} + dependencies: + '@types/mdast': 3.0.10 + mdast-util-math: 2.0.2 + micromark-extension-math: 2.0.2 + unified: 10.1.2 + dev: false + + /remark-mdx/2.1.5: + resolution: {integrity: sha512-A8vw5s+BgOa968Irt8BO7DfWJTE0Fe7Ge3hX8zzDB1DnwMZTNdK6qF2IcFao+/7nzk1vSysKcFp+3ku4vhMpaQ==} + dependencies: + mdast-util-mdx: 2.0.0 + micromark-extension-mdxjs: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-parse/10.0.1: + resolution: {integrity: sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==} + dependencies: + '@types/mdast': 3.0.10 + mdast-util-from-markdown: 1.2.0 + unified: 10.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-reading-time/2.0.1: + resolution: {integrity: sha512-fy4BKy9SRhtYbEHvp6AItbRTnrhiDGbqLQTSYVbQPGuRCncU1ubSsh9p/W5QZSxtYcUXv8KGL0xBgPLyNJA1xw==} + dependencies: + estree-util-is-identifier-name: 2.0.1 + estree-util-value-to-estree: 1.3.0 + reading-time: 1.5.0 + unist-util-visit: 3.1.0 + dev: false + + /remark-rehype/10.1.0: + resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==} + dependencies: + '@types/hast': 2.3.4 + '@types/mdast': 3.0.10 + mdast-util-to-hast: 12.2.4 + unified: 10.1.2 + dev: false + + /remove-accents/0.4.2: + resolution: {integrity: sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U=} + dev: false + + /sade/1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + dependencies: + mri: 1.2.0 + dev: false + + /scheduler/0.23.0: + resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + dependencies: + loose-envify: 1.4.0 + dev: false + + /scroll-into-view-if-needed/3.0.4: + resolution: {integrity: sha512-s+/F50jwTOUt+u5oEIAzum9MN2lUQNvWBe/zfEsVQcbaERjGkKLq1s+2wCHkahMLC8nMLbzMVKivx9JhunXaZg==} + dependencies: + compute-scroll-into-view: 2.0.4 + dev: false + + /section-matter/1.0.0: + resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} + engines: {node: '>=4'} + dependencies: + extend-shallow: 2.0.1 + kind-of: 6.0.3 + dev: false + + /shebang-command/1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + dependencies: + shebang-regex: 1.0.0 + dev: false + + /shebang-regex/1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + dev: false + + /shiki/0.12.1: + resolution: {integrity: sha512-aieaV1m349rZINEBkjxh2QbBvFFQOlgqYTNtCal82hHj4dDZ76oMlQIX+C7ryerBTDiga3e5NfH6smjdJ02BbQ==} + dependencies: + jsonc-parser: 3.2.0 + vscode-oniguruma: 1.7.0 + vscode-textmate: 8.0.0 + dev: false + + /signal-exit/3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: false + + /slash/3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: false + + /sort-keys/5.0.0: + resolution: {integrity: sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==} + engines: {node: '>=12'} + dependencies: + is-plain-obj: 4.1.0 + dev: false + + /source-map-js/1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: false + + /source-map/0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + dev: false + + /space-separated-tokens/2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + dev: false + + /sprintf-js/1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: false + + /stringify-entities/4.0.3: + resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==} + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + dev: false + + /strip-bom-string/1.0.0: + resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} + engines: {node: '>=0.10.0'} + dev: false + + /strip-eof/1.0.0: + resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} + engines: {node: '>=0.10.0'} + dev: false + + /style-to-object/0.3.0: + resolution: {integrity: sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==} + dependencies: + inline-style-parser: 0.1.1 + dev: false + + /styled-jsx/5.1.0_react@18.2.0: + resolution: {integrity: sha512-/iHaRJt9U7T+5tp6TRelLnqBqiaIT0HsO0+vgyj8hK2KUk7aejFqRrumqPUlAqDwAj8IbS/1hk3IhBAAK/FCUQ==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + dependencies: + client-only: 0.0.1 + react: 18.2.0 + dev: false + + /supports-color/4.5.0: + resolution: {integrity: sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw==} + engines: {node: '>=4'} + dependencies: + has-flag: 2.0.0 + dev: false + + /title/3.5.3: + resolution: {integrity: sha512-20JyowYglSEeCvZv3EZ0nZ046vLarO37prvV0mbtQV7C8DJPGgN967r8SJkqd3XK3K3lD3/Iyfp3avjfil8Q2Q==} + hasBin: true + dependencies: + arg: 1.0.0 + chalk: 2.3.0 + clipboardy: 1.2.2 + titleize: 1.0.0 + dev: false + + /titleize/1.0.0: + resolution: {integrity: sha1-fTUHIgYYMLpmF2MeDP0+oIOY2Vo=} + engines: {node: '>=0.10.0'} + dev: false + + /trim-lines/3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + dev: false + + /trough/2.1.0: + resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} + dev: false + + /tslib/2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} + dev: false + + /type-fest/1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + dev: false + + /typescript/4.9.3: + resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /unified/10.1.2: + resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} + dependencies: + '@types/unist': 2.0.6 + bail: 2.0.2 + extend: 3.0.2 + is-buffer: 2.0.5 + is-plain-obj: 4.1.0 + trough: 2.1.0 + vfile: 5.3.6 + dev: false + + /unist-builder/3.0.0: + resolution: {integrity: sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /unist-util-find-after/4.0.1: + resolution: {integrity: sha512-QO/PuPMm2ERxC6vFXEPtmAutOopy5PknD+Oq64gGwxKtk4xwo9Z97t9Av1obPmGU0IyTa6EKYUfTrK2QJS3Ozw==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + dev: false + + /unist-util-generated/2.0.0: + resolution: {integrity: sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw==} + dev: false + + /unist-util-is/5.1.1: + resolution: {integrity: sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==} + dev: false + + /unist-util-position-from-estree/1.1.1: + resolution: {integrity: sha512-xtoY50b5+7IH8tFbkw64gisG9tMSpxDjhX9TmaJJae/XuxQ9R/Kc8Nv1eOsf43Gt4KV/LkriMy9mptDr7XLcaw==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /unist-util-position/4.0.3: + resolution: {integrity: sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /unist-util-remove-position/4.0.1: + resolution: {integrity: sha512-0yDkppiIhDlPrfHELgB+NLQD5mfjup3a8UYclHruTJWmY74je8g+CIFr79x5f6AkmzSwlvKLbs63hC0meOMowQ==} + dependencies: + '@types/unist': 2.0.6 + unist-util-visit: 4.1.1 + dev: false + + /unist-util-remove/3.1.1: + resolution: {integrity: sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + unist-util-visit-parents: 5.1.1 + dev: false + + /unist-util-stringify-position/3.0.2: + resolution: {integrity: sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /unist-util-visit-parents/4.1.1: + resolution: {integrity: sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + dev: false + + /unist-util-visit-parents/5.1.1: + resolution: {integrity: sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + dev: false + + /unist-util-visit/3.1.0: + resolution: {integrity: sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + unist-util-visit-parents: 4.1.1 + dev: false + + /unist-util-visit/4.1.1: + resolution: {integrity: sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + unist-util-visit-parents: 5.1.1 + dev: false + + /uvu/0.5.6: + resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} + engines: {node: '>=8'} + hasBin: true + dependencies: + dequal: 2.0.3 + diff: 5.1.0 + kleur: 4.1.5 + sade: 1.8.1 + dev: false + + /vfile-location/4.0.1: + resolution: {integrity: sha512-JDxPlTbZrZCQXogGheBHjbRWjESSPEak770XwWPfw5mTc1v1nWGLB/apzZxsx8a0SJVfF8HK8ql8RD308vXRUw==} + dependencies: + '@types/unist': 2.0.6 + vfile: 5.3.6 + dev: false + + /vfile-matter/3.0.1: + resolution: {integrity: sha512-CAAIDwnh6ZdtrqAuxdElUqQRQDQgbbIrYtDYI8gCjXS1qQ+1XdLoK8FIZWxJwn0/I+BkSSZpar3SOgjemQz4fg==} + dependencies: + '@types/js-yaml': 4.0.5 + is-buffer: 2.0.5 + js-yaml: 4.1.0 + dev: false + + /vfile-message/3.1.3: + resolution: {integrity: sha512-0yaU+rj2gKAyEk12ffdSbBfjnnj+b1zqTBv3OQCTn8yEB02bsPizwdBPrLJjHnK+cU9EMMcUnNv938XcZIkmdA==} + dependencies: + '@types/unist': 2.0.6 + unist-util-stringify-position: 3.0.2 + dev: false + + /vfile/5.3.6: + resolution: {integrity: sha512-ADBsmerdGBs2WYckrLBEmuETSPyTD4TuLxTrw0DvjirxW1ra4ZwkbzG8ndsv3Q57smvHxo677MHaQrY9yxH8cA==} + dependencies: + '@types/unist': 2.0.6 + is-buffer: 2.0.5 + unist-util-stringify-position: 3.0.2 + vfile-message: 3.1.3 + dev: false + + /vscode-oniguruma/1.7.0: + resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} + dev: false + + /vscode-textmate/8.0.0: + resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} + dev: false + + /web-namespaces/2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + dev: false + + /which/1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: false + + /yallist/2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + dev: false + + /yocto-queue/0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: false + + /zod/3.20.2: + resolution: {integrity: sha512-1MzNQdAvO+54H+EaK5YpyEy0T+Ejo/7YLHS93G3RnYWh5gaotGHwGeN/ZO687qEDU2y4CdStQYXVHIgrUl5UVQ==} + dev: false + + /zwitch/2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + dev: false diff --git a/sdk/typescript/docs/scripts/build-prod-docs.sh b/sdk/typescript/docs/scripts/build-prod-docs.sh new file mode 100755 index 0000000000..5f37401e87 --- /dev/null +++ b/sdk/typescript/docs/scripts/build-prod-docs.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf ../../../dist/ts/docs/sdk/typescript || true + +# run the build +npm run build + +# move the output outside of the yarn/npm workspaces +mkdir -p ../../../dist/ts/docs/sdk +mv out ../../../dist/ts/docs/sdk/typescript + +echo "Output can be found in:" +realpath ../../../dist/ts/docs/sdk/typescript diff --git a/sdk/typescript/docs/theme.config.tsx b/sdk/typescript/docs/theme.config.tsx new file mode 100644 index 0000000000..2db2901904 --- /dev/null +++ b/sdk/typescript/docs/theme.config.tsx @@ -0,0 +1,43 @@ +import React from 'react'; +import { DocsThemeConfig, useConfig } from 'nextra-theme-docs'; +import { useRouter } from 'next/router'; + +const config: DocsThemeConfig = { + logo: Nym Typescript SDK, + project: { + link: 'https://github.com/nymtech/nym', + }, + chat: { + link: 'https://discord.gg/nym', + }, + docsRepositoryBase: 'https://github.com/nymtech/nym/tree/develop/sdk/typescript/docs', + footer: { + text: 'Nym Typescript SDK', + }, + useNextSeoProps() { + return { + titleTemplate: '%s | Nym Typescript SDK', + }; + }, + // head: () => { + // const { asPath, defaultLocale, locale } = useRouter(); + // const { frontMatter } = useConfig(); + // const url = `https://nymtech.net/docs/sdk/typescript/${defaultLocale === locale ? asPath : `/${locale}${asPath}`}`; + // + // return ( + // <> + // + // + // + // + // ); + // }, +}; + +export default config; diff --git a/sdk/typescript/docs/tsconfig.json b/sdk/typescript/docs/tsconfig.json new file mode 100644 index 0000000000..1563f3e878 --- /dev/null +++ b/sdk/typescript/docs/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": false, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "incremental": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve" + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +} diff --git a/sdk/typescript/examples/chat-app/parcel/package.json b/sdk/typescript/examples/chat-app/parcel/package.json index 98260f0f38..4159cc023c 100644 --- a/sdk/typescript/examples/chat-app/parcel/package.json +++ b/sdk/typescript/examples/chat-app/parcel/package.json @@ -6,7 +6,7 @@ "source": "src/index.html", "browserslist": "> 0.5%, last 2 versions, not dead", "dependencies": { - "@nymproject/sdk": "1" + "@nymproject/sdk": "1.2.0-rc.1" }, "devDependencies": { "@types/jest": "^27.0.1", diff --git a/sdk/typescript/examples/chat-app/parcel/src/index.html b/sdk/typescript/examples/chat-app/parcel/src/index.html index 4e4550c539..94eb12f5b2 100644 --- a/sdk/typescript/examples/chat-app/parcel/src/index.html +++ b/sdk/typescript/examples/chat-app/parcel/src/index.html @@ -5,7 +5,7 @@ Nym WebAssembly Demo - + diff --git a/sdk/typescript/examples/chat-app/plain-html/package.json b/sdk/typescript/examples/chat-app/plain-html/package.json index a937165155..31b37c2cb2 100644 --- a/sdk/typescript/examples/chat-app/plain-html/package.json +++ b/sdk/typescript/examples/chat-app/plain-html/package.json @@ -4,7 +4,7 @@ "version": "1.0.0", "license": "Apache-2.0", "dependencies": { - "@nymproject/sdk": "1" + "@nymproject/sdk": "1.2.0-rc.1" }, "devDependencies": { "@babel/core": "^7.15.0", diff --git a/sdk/typescript/examples/chat-app/plain-html/src/index.ts b/sdk/typescript/examples/chat-app/plain-html/src/index.ts deleted file mode 100644 index a0e429beb1..0000000000 --- a/sdk/typescript/examples/chat-app/plain-html/src/index.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { createNymMixnetClient, NymMixnetClient } from '@nymproject/sdk'; -import { displayReceived, sendMessageTo, displaySenderAddress } from './dom-utils'; - -let nym: NymMixnetClient | null = null; - -/** - * The main entry point - */ -async function main() { - nym = await createNymMixnetClient(); - - // add nym client to the Window globally, so that it can be used from the dev tools console - (window as any).nym = nym; - - if (!nym) { - console.error('Oh no! Could not create client'); - return; - } - - const nymApiUrl = 'https://validator.nymtech.net/api'; - const preferredGatewayIdentityKey = 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM'; - - // subscribe to connect event, so that we can show the client's address - nym.events.subscribeToConnected((e) => { - if (e.args.address) { - displaySenderAddress(e.args.address); - } - }); - - // subscribe to message received events and show any string messages received - nym.events.subscribeToTextMessageReceivedEvent((e) => { - displayReceived(e.args.payload); - }); - - const sendButton: HTMLButtonElement = document.querySelector('#send-button') as HTMLButtonElement; - if (sendButton) { - sendButton.onclick = function () { - if (nym) { - sendMessageTo(nym); - } - }; - } - - nym.events.subscribeToRawMessageReceivedEvent((e) => console.log('Received: ', e.args.payload)); - - // start up the client - await nym.client.start({ - clientId: 'My awesome client', - nymApiUrl, - preferredGatewayIdentityKey, - }); -} - -// wait for the html to load -window.addEventListener('DOMContentLoaded', () => { - // let's do this! - main(); -}); diff --git a/sdk/typescript/examples/chat-app/plain-html/tsconfig.json b/sdk/typescript/examples/chat-app/plain-html/tsconfig.json index 86902367db..25e78e9f5f 100644 --- a/sdk/typescript/examples/chat-app/plain-html/tsconfig.json +++ b/sdk/typescript/examples/chat-app/plain-html/tsconfig.json @@ -4,6 +4,5 @@ "jsx": "react-jsx", "outDir": "./dist" }, - "include": ["src/**/*.ts", "src/**/*.tsx"], "exclude": ["node_modules", "build", "dist"] } diff --git a/sdk/typescript/examples/chat-app/plain-html/webpack.common.js b/sdk/typescript/examples/chat-app/plain-html/webpack.common.js index ae6ef6dc8e..121d113bcd 100644 --- a/sdk/typescript/examples/chat-app/plain-html/webpack.common.js +++ b/sdk/typescript/examples/chat-app/plain-html/webpack.common.js @@ -20,7 +20,7 @@ module.exports = mergeWithRules({ ]), { entry: { - index: path.resolve(__dirname, 'src/index.ts'), + index: path.resolve(__dirname, '../../shared/index.ts'), }, output: { path: path.resolve(__dirname, 'dist'), diff --git a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json index 5af2e7b841..6c97cd50dc 100644 --- a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json +++ b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json @@ -9,7 +9,7 @@ "@mui/material": "^5.0.1", "@mui/styles": "^5.0.1", "react-mui-dropzone": "^4.0.6", - "@nymproject/sdk": "1", + "@nymproject/sdk": "1.2.0-rc.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", diff --git a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/src/App.tsx b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/src/App.tsx index c2252585de..cfb5a57b56 100644 --- a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/src/App.tsx +++ b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/src/App.tsx @@ -31,7 +31,7 @@ import { ThemeToggle } from './ThemeToggle'; import { AppContextProvider, useAppContext } from './context'; import { MixnetContextProvider, parseBinaryMessageHeaders, useMixnetContext } from './context/mixnet'; // eslint-disable-next-line import/no-relative-packages -import Logo from '../../../../../assets/logo/logo-circle.svg'; +import Logo from '../../../../../../assets/logo/logo-circle.svg'; export const AppTheme: FCWithChildren = ({ children }) => { const { mode } = useAppContext(); diff --git a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/src/context/mixnet.tsx b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/src/context/mixnet.tsx index 1a2588ce40..54b8d749d5 100644 --- a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/src/context/mixnet.tsx +++ b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/src/context/mixnet.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import { createNymMixnetClient, IWebWorkerEvents, MimeTypes, NymClientConfig, NymMixnetClient } from '@nymproject/sdk'; - export interface BinaryMessageHeaders { filename: string; mimeType: string; diff --git a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/webpack.common.js b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/webpack.common.js index 459c5495e4..d42d331663 100644 --- a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/webpack.common.js +++ b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/webpack.common.js @@ -1,6 +1,6 @@ const path = require('path'); const { mergeWithRules } = require('webpack-merge'); -const { webpackCommon } = require('../.webpack/webpack.base'); +const { webpackCommon } = require('../../.webpack/webpack.base'); module.exports = mergeWithRules({ module: { diff --git a/sdk/typescript/examples/chrome-extension/package.json b/sdk/typescript/examples/chrome-extension/package.json index cf9d9927d0..6db0895ef4 100644 --- a/sdk/typescript/examples/chrome-extension/package.json +++ b/sdk/typescript/examples/chrome-extension/package.json @@ -1,5 +1,5 @@ { - "name": "chrome-extension", + "name": "@nymproject/sdk-example-chrome-extension", "version": "1.0.0", "description": "This is an example of how Nym can be used within the context of a Chrome extension.", "main": "index.js", @@ -15,6 +15,6 @@ "webpack-cli": "^5.1.4" }, "dependencies": { - "@nymproject/sdk": "^1.1.8" + "@nymproject/sdk": "1.2.0-rc.1" } } diff --git a/sdk/typescript/examples/chrome-extension/tsconfig.json b/sdk/typescript/examples/chrome-extension/tsconfig.json new file mode 100644 index 0000000000..704db85a1c --- /dev/null +++ b/sdk/typescript/examples/chrome-extension/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "declaration": false, + "declarationMap": false + }, + "exclude": ["node_modules", "dist"] +} diff --git a/sdk/typescript/examples/firefox-extension/package.json b/sdk/typescript/examples/firefox-extension/package.json index 70160f5150..8113b5b123 100644 --- a/sdk/typescript/examples/firefox-extension/package.json +++ b/sdk/typescript/examples/firefox-extension/package.json @@ -1,5 +1,5 @@ { - "name": "firefox-extension", + "name": "@nymproject/sdk-example-firefox-extension", "version": "1.0.0", "description": "This is an example of how Nym can be used within the context of a Firefox extension.", "main": "index.js", @@ -8,12 +8,13 @@ "devDependencies": { "copy-webpack-plugin": "^11.0.0", "webpack": "^5.88.1", - "webpack-cli": "^5.1.4" + "webpack-cli": "^5.1.4", + "worker-loader": "^3.0.8" }, "scripts": { "build": "yarn webpack" }, "dependencies": { - "worker-loader": "^3.0.8" + "@nymproject/sdk": "1.2.0-rc.1" } } diff --git a/sdk/typescript/examples/firefox-extension/src/background.ts b/sdk/typescript/examples/firefox-extension/src/background.ts new file mode 100644 index 0000000000..6d15c9ce9f --- /dev/null +++ b/sdk/typescript/examples/firefox-extension/src/background.ts @@ -0,0 +1,114 @@ +// main.js +// Simple example of how to load Nym's TypeScript SDK and bind it to a DOM. +// Look at dom-utils.js for the DOM utility functionality referenced here. + +// Import the Nym mixnet ESM module. +// Import The web workers for the Nym mixnet ESM module.These are required for to run the Nym mixnet client. + +import { createNymMixnetClient } from '../../../packages/sdk/dist/full-fat/index.js'; +import '../../../packages/sdk/dist/full-fat/web-worker-0.js'; +import '../../../packages/sdk/dist/full-fat/web-worker-1.js'; + +export type BackgroundState = { + isReady: boolean; + address: string; + recipient: string; + messageLog: { type: string; message: string }[]; +}; + +const backgroundState: BackgroundState = { + isReady: false, + address: '', + recipient: '', + messageLog: [], +}; + +async function initBackground() { + // Initialize the Nym mixnet client. + let nymClient = await createNymMixnetClient().catch((err) => { + console.log(err); + }); + if (!nymClient) { + console.error('Oh no! Could not create client'); + return; + } + const nymApiUrl = 'https://validator.nymtech.net/api'; + const preferredGatewayIdentityKey = 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM'; + + // subscribe to connect event, so that we can show the client's address + nymClient.events.subscribeToConnected((e) => { + if (e.args.address) { + backgroundState.address = e.args.address; + browser.runtime.sendMessage({ + type: 'displaySenderAddress', + message: backgroundState.address, + }); + } + }); + + // subscribe to message received events and show any string messages received + nymClient.events.subscribeToTextMessageReceivedEvent((e) => { + backgroundState.messageLog.push({ + type: 'received', + message: e.args.payload, + }); + browser.runtime.sendMessage({ + type: 'displayReceived', + message: e.args.payload, + }); + }); + + nymClient.events.subscribeToRawMessageReceivedEvent((e) => console.log('Received: ', e.args.payload)); + await nymClient.client.start({ + clientId: 'My awesome client', + nymApiUrl, + preferredGatewayIdentityKey, + }); + browser.runtime.onMessage.addListener(async (data) => { + switch (data.type) { + case 'nymClientSendMessage': + if (nymClient) { + await nymClient.client.send({ + payload: { + message: data.message, + mimeType: 'text/plain', + }, + recipient: data.recipient, + }); + backgroundState.messageLog.push({ + type: 'sent', + message: data.message, + }); + break; + } + } + }); + backgroundState.isReady = true; +} + +window.addEventListener('DOMContentLoaded', () => { + browser.runtime.onMessage.addListener((data) => { + switch (data.type) { + case 'popupReady': + if (backgroundState.isReady) { + browser.runtime.sendMessage({ + type: 'displaySenderAddress', + message: backgroundState.address, + }); + browser.runtime.sendMessage({ + type: 'displayMessageLog', + message: backgroundState.messageLog, + }); + browser.runtime.sendMessage({ + type: 'updateRecipient', + message: backgroundState.recipient, + }); + } else { + initBackground(); + } + break; + case 'updateRecipient': + backgroundState.recipient = data.message; + } + }); +}); diff --git a/sdk/typescript/examples/firefox-extension/src/dom-utils.ts b/sdk/typescript/examples/firefox-extension/src/dom-utils.ts new file mode 100644 index 0000000000..89b21bc0c5 --- /dev/null +++ b/sdk/typescript/examples/firefox-extension/src/dom-utils.ts @@ -0,0 +1,35 @@ +// dom-utils.js +// Contains utility functionality to help manipulate the DOM elements necessary to demonstrate the Nym example. + +import { BackgroundState } from './background'; +import { displayReceived, displaySend, displaySenderAddress } from '../../shared/dom-utils'; + +/** + * Create a Sphinx packet and send it to the mixnet through the gateway node. + * + * Message and recipient are taken from the values in the user interface. + * + * @param {Client} nymClient the nym client to use for message sending + */ +async function sendMessageTo() { + const message = (document.getElementById('message') as HTMLFormElement).value; + const recipient = (document.getElementById('recipient') as HTMLFormElement).value; + browser.runtime.sendMessage({ + type: 'nymClientSendMessage', + message, + recipient, + }); + displaySend(message); +} + +function displayMessageLog(messageLog: BackgroundState['messageLog']) { + for (let i = 0; i < messageLog.length; i++) { + if (messageLog[i].type === 'sent') { + displaySend(messageLog[i].message); + } else if (messageLog[i].type === 'received') { + displayReceived(messageLog[i].message); + } + } +} + +export { sendMessageTo, displaySend, displayReceived, displaySenderAddress, displayMessageLog }; diff --git a/sdk/typescript/examples/firefox-extension/src/popup.ts b/sdk/typescript/examples/firefox-extension/src/popup.ts new file mode 100644 index 0000000000..9c20100bd8 --- /dev/null +++ b/sdk/typescript/examples/firefox-extension/src/popup.ts @@ -0,0 +1,40 @@ +// Import the DOM utility functionality. +import { displaySenderAddress, displayReceived, sendMessageTo, displayMessageLog } from './dom-utils'; + +window.addEventListener('DOMContentLoaded', () => { + const sendButton = document.querySelector('#send-button') as HTMLButtonElement; + if (sendButton) { + sendButton.onclick = function () { + sendMessageTo(); + }; + } + const recipient = document.getElementById('recipient') as HTMLFormElement; + recipient.onchange = () => { + browser.runtime.sendMessage({ + type: 'updateRecipient', + message: recipient.value, + }); + }; + browser.runtime.onMessage.addListener((data) => { + switch (data.type) { + case 'displaySenderAddress': + displaySenderAddress(data.message); + break; + case 'displayReceived': + displayReceived(data.message); + break; + // case 'sendMessageTo': + // sendMessageTo(data.message); + // break; + case 'displayMessageLog': + displayMessageLog(data.message); + break; + case 'updateRecipient': + recipient.value = data.message; + } + }); + browser.runtime.sendMessage({ + type: 'popupReady', + message: '', + }); +}); diff --git a/sdk/typescript/examples/firefox-extension/tsconfig.json b/sdk/typescript/examples/firefox-extension/tsconfig.json new file mode 100644 index 0000000000..efe834e509 --- /dev/null +++ b/sdk/typescript/examples/firefox-extension/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "declaration": false, + "declarationMap": false + }, + "exclude": ["node_modules", "dist"] +} diff --git a/sdk/typescript/examples/node-tester/parcel/package.json b/sdk/typescript/examples/node-tester/parcel/package.json index 27c563a40e..61750e513c 100644 --- a/sdk/typescript/examples/node-tester/parcel/package.json +++ b/sdk/typescript/examples/node-tester/parcel/package.json @@ -6,7 +6,7 @@ "source": "src/index.html", "browserslist": "> 0.5%, last 2 versions, not dead", "dependencies": { - "@nymproject/sdk": "1" + "@nymproject/sdk": "1.2.0-rc.1" }, "devDependencies": { "@types/jest": "^27.0.1", diff --git a/sdk/typescript/examples/node-tester/plain-html/package.json b/sdk/typescript/examples/node-tester/plain-html/package.json index b80734f6d4..4dd3603ab4 100644 --- a/sdk/typescript/examples/node-tester/plain-html/package.json +++ b/sdk/typescript/examples/node-tester/plain-html/package.json @@ -4,7 +4,7 @@ "version": "1.0.0", "license": "Apache-2.0", "dependencies": { - "@nymproject/sdk": "1" + "@nymproject/sdk": "1.2.0-rc.1" }, "devDependencies": { "@babel/core": "^7.15.0", diff --git a/sdk/typescript/examples/node-tester/react/package.json b/sdk/typescript/examples/node-tester/react/package.json index d453a0c291..57d8a58ca0 100644 --- a/sdk/typescript/examples/node-tester/react/package.json +++ b/sdk/typescript/examples/node-tester/react/package.json @@ -8,7 +8,7 @@ "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.14.0", "@mui/material": "^5.14.0", - "@nymproject/sdk": "1", + "@nymproject/sdk": "1.2.0-rc.1", "parcel": "^2.9.3", "react": "^18.2.0", "react-dom": "^18.2.0" diff --git a/ts-packages/react-webpack-with-theme-example/README.md b/sdk/typescript/examples/react/mui-theme/README.md similarity index 100% rename from ts-packages/react-webpack-with-theme-example/README.md rename to sdk/typescript/examples/react/mui-theme/README.md diff --git a/ts-packages/react-webpack-with-theme-example/package.json b/sdk/typescript/examples/react/mui-theme/package.json similarity index 100% rename from ts-packages/react-webpack-with-theme-example/package.json rename to sdk/typescript/examples/react/mui-theme/package.json diff --git a/ts-packages/react-webpack-with-theme-example/src/App.tsx b/sdk/typescript/examples/react/mui-theme/src/App.tsx similarity index 100% rename from ts-packages/react-webpack-with-theme-example/src/App.tsx rename to sdk/typescript/examples/react/mui-theme/src/App.tsx diff --git a/ts-packages/react-webpack-with-theme-example/src/ThemeToggle.tsx b/sdk/typescript/examples/react/mui-theme/src/ThemeToggle.tsx similarity index 100% rename from ts-packages/react-webpack-with-theme-example/src/ThemeToggle.tsx rename to sdk/typescript/examples/react/mui-theme/src/ThemeToggle.tsx diff --git a/ts-packages/react-webpack-with-theme-example/src/context/index.tsx b/sdk/typescript/examples/react/mui-theme/src/context/index.tsx similarity index 100% rename from ts-packages/react-webpack-with-theme-example/src/context/index.tsx rename to sdk/typescript/examples/react/mui-theme/src/context/index.tsx diff --git a/ts-packages/react-webpack-with-theme-example/src/index.html b/sdk/typescript/examples/react/mui-theme/src/index.html similarity index 100% rename from ts-packages/react-webpack-with-theme-example/src/index.html rename to sdk/typescript/examples/react/mui-theme/src/index.html diff --git a/ts-packages/react-webpack-with-theme-example/src/index.tsx b/sdk/typescript/examples/react/mui-theme/src/index.tsx similarity index 100% rename from ts-packages/react-webpack-with-theme-example/src/index.tsx rename to sdk/typescript/examples/react/mui-theme/src/index.tsx diff --git a/ts-packages/react-webpack-with-theme-example/src/tests/App.test.tsx b/sdk/typescript/examples/react/mui-theme/src/tests/App.test.tsx similarity index 100% rename from ts-packages/react-webpack-with-theme-example/src/tests/App.test.tsx rename to sdk/typescript/examples/react/mui-theme/src/tests/App.test.tsx diff --git a/ts-packages/react-components/src/theme/mui-theme.d.ts b/sdk/typescript/examples/react/mui-theme/src/theme/mui-theme.d.ts similarity index 100% rename from ts-packages/react-components/src/theme/mui-theme.d.ts rename to sdk/typescript/examples/react/mui-theme/src/theme/mui-theme.d.ts diff --git a/ts-packages/mui-theme/src/typings/FC.d.ts b/sdk/typescript/examples/react/mui-theme/src/typings/FC.d.ts similarity index 100% rename from ts-packages/mui-theme/src/typings/FC.d.ts rename to sdk/typescript/examples/react/mui-theme/src/typings/FC.d.ts diff --git a/ts-packages/react-webpack-with-theme-example/tsconfig.json b/sdk/typescript/examples/react/mui-theme/tsconfig.json similarity index 100% rename from ts-packages/react-webpack-with-theme-example/tsconfig.json rename to sdk/typescript/examples/react/mui-theme/tsconfig.json diff --git a/ts-packages/react-webpack-with-theme-example/tsconfig.prod.json b/sdk/typescript/examples/react/mui-theme/tsconfig.prod.json similarity index 100% rename from ts-packages/react-webpack-with-theme-example/tsconfig.prod.json rename to sdk/typescript/examples/react/mui-theme/tsconfig.prod.json diff --git a/ts-packages/react-webpack-with-theme-example/webpack.common.js b/sdk/typescript/examples/react/mui-theme/webpack.common.js similarity index 100% rename from ts-packages/react-webpack-with-theme-example/webpack.common.js rename to sdk/typescript/examples/react/mui-theme/webpack.common.js diff --git a/ts-packages/react-webpack-with-theme-example/webpack.config.js b/sdk/typescript/examples/react/mui-theme/webpack.config.js similarity index 100% rename from ts-packages/react-webpack-with-theme-example/webpack.config.js rename to sdk/typescript/examples/react/mui-theme/webpack.config.js diff --git a/ts-packages/react-webpack-with-theme-example/webpack.prod.js b/sdk/typescript/examples/react/mui-theme/webpack.prod.js similarity index 100% rename from ts-packages/react-webpack-with-theme-example/webpack.prod.js rename to sdk/typescript/examples/react/mui-theme/webpack.prod.js diff --git a/ts-packages/react-webpack-with-theme-example/yarn-error.log b/sdk/typescript/examples/react/mui-theme/yarn-error.log similarity index 100% rename from ts-packages/react-webpack-with-theme-example/yarn-error.log rename to sdk/typescript/examples/react/mui-theme/yarn-error.log diff --git a/sdk/typescript/examples/react/sdk-react/package.json b/sdk/typescript/examples/react/sdk-react/package.json new file mode 100644 index 0000000000..1c4a84f5ce --- /dev/null +++ b/sdk/typescript/examples/react/sdk-react/package.json @@ -0,0 +1,43 @@ +{ + "name": "@nymproject/sdk-example-sdk-react", + "version": "1.0.0", + "license": "Apache-2.0", + "source": "src/index.html", + "browserslist": "> 0.5%, last 2 versions, not dead", + "dependencies": { + "@nymproject/sdk": "file:../../../packages/sdk", + "@nymproject/sdk-react": "file:../../../packages/sdk-react" + }, + "devDependencies": { + "@types/jest": "^27.0.1", + "@types/node": "^16.7.13", + "@typescript-eslint/eslint-plugin": "^5.13.0", + "@typescript-eslint/parser": "^5.13.0", + "eslint": "^8.10.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-airbnb-typescript": "^16.1.0", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-root-import": "^1.0.4", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^26.1.1", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-prettier": "^4.0.0", + "jest": "^27.1.0", + "mini-css-extract-plugin": "^2.2.2", + "npm-run-all": "^4.1.5", + "prettier": "^2.8.7", + "ts-jest": "^27.0.5", + "typescript": "^4.6.2" + }, + "scripts": { + "start": "npx parcel", + "build": "npx parcel build --no-optimize", + "build:serve": "npx serve dist", + "test": "jest", + "test:watch": "jest --watch", + "tsc": "tsc", + "tsc:watch": "tsc --watch", + "lint": "eslint src", + "lint:fix": "eslint src --fix" + } +} diff --git a/sdk/typescript/examples/react/sdk-react/src/App.tsx b/sdk/typescript/examples/react/sdk-react/src/App.tsx new file mode 100644 index 0000000000..999df1798e --- /dev/null +++ b/sdk/typescript/examples/react/sdk-react/src/App.tsx @@ -0,0 +1,97 @@ +import * as React from 'react'; +import { MixnetContextProvider, useMixnetContext } from '@nymproject/sdk-react'; +import type { EventHandlerFn, StringMessageReceivedEvent } from '@nymproject/sdk'; + +export const Content: FCWithChildren = () => { + const { isReady, address, sendTextMessage, events } = useMixnetContext(); + const log = React.useRef([]); + const [trigger, setTrigger] = React.useState(new Date()); + const formElementRef = React.createRef(); + + const appendLog = (type: React.ReactNode, node?: React.ReactNode) => { + const timestamp = new Date().toLocaleTimeString(); + log.current.push( +
+
+ {timestamp} {type} +
+ {node || null} +
+
, + ); + setTrigger(new Date()); + }; + + const handleMessage = React.useCallback>((e) => { + appendLog( + ⬅️ Received, +
+
{e.args.payload}
+
, + ); + }, []); + + React.useEffect(() => { + if (!events || !isReady) { + return undefined; + } + + appendLog(Connected); + + const unsubscribeFn = events.subscribeToTextMessageReceivedEvent(handleMessage); + + // when unmounting unsubscribe will be called + return unsubscribeFn; + }, [isReady]); + + const handleSend = async () => { + if (!formElementRef.current || !address) { + return; + } + + const message = formElementRef.current.value; + + appendLog( + ➡️️ Sent, +
+
{message}
+
, + ); + setTrigger(new Date()); + + await sendTextMessage({ payload: message, recipient: address }); + }; + + if (!isReady) { + return ( +
+

Nym SDK Mixnet React Context

+
Loading...
+
+ ); + } + + return ( +
+

Nym SDK Mixnet React Context

+
+

+ Client address: {address} +

+

+ + +

+
+

Logs

+ {log.current.map((item) => ( + <>{item} + ))} +
+ ); +}; +export const App: FCWithChildren = () => ( + + + +); diff --git a/sdk/typescript/examples/react/sdk-react/src/index.html b/sdk/typescript/examples/react/sdk-react/src/index.html new file mode 100644 index 0000000000..7e8b531e5f --- /dev/null +++ b/sdk/typescript/examples/react/sdk-react/src/index.html @@ -0,0 +1,20 @@ + + + + + + + Nym WebAssembly Demo + + + + + +
+ + + diff --git a/sdk/typescript/examples/react/sdk-react/src/index.tsx b/sdk/typescript/examples/react/sdk-react/src/index.tsx new file mode 100644 index 0000000000..595758331e --- /dev/null +++ b/sdk/typescript/examples/react/sdk-react/src/index.tsx @@ -0,0 +1,7 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import { App } from './App'; + +const container = document.getElementById('app'); +const root = createRoot(container!); // createRoot(container!) if you use TypeScript +root.render(); diff --git a/ts-packages/react-components/src/typings/FC.d.ts b/sdk/typescript/examples/react/sdk-react/src/typings/FC.d.ts similarity index 100% rename from ts-packages/react-components/src/typings/FC.d.ts rename to sdk/typescript/examples/react/sdk-react/src/typings/FC.d.ts diff --git a/sdk/typescript/examples/react/sdk-react/tsconfig.json b/sdk/typescript/examples/react/sdk-react/tsconfig.json new file mode 100644 index 0000000000..86902367db --- /dev/null +++ b/sdk/typescript/examples/react/sdk-react/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "jsx": "react-jsx", + "outDir": "./dist" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "build", "dist"] +} diff --git a/sdk/typescript/examples/chat-app/plain-html/src/dom-utils.ts b/sdk/typescript/examples/shared/dom-utils.ts similarity index 58% rename from sdk/typescript/examples/chat-app/plain-html/src/dom-utils.ts rename to sdk/typescript/examples/shared/dom-utils.ts index 7e98532ea3..3025373f82 100644 --- a/sdk/typescript/examples/chat-app/plain-html/src/dom-utils.ts +++ b/sdk/typescript/examples/shared/dom-utils.ts @@ -7,6 +7,7 @@ import { NymMixnetClient, MimeTypes } from '@nymproject/sdk'; * * @param {Client} nymClient the nym client to use for message sending */ + export async function sendMessageTo(nym: NymMixnetClient) { const message = (document.getElementById('message') as HTMLFormElement).value; const recipient = (document.getElementById('recipient') as HTMLFormElement).value; @@ -15,22 +16,33 @@ export async function sendMessageTo(nym: NymMixnetClient) { displaySend(message); } +const createISOTimeStamp = () => new Date().toISOString().substring(11, 16); + +const createChatEntry = ({ message, sendOrReceive }: { message: string; sendOrReceive: 'SEND' | 'RECEIVE' }) => { + const timestamp = createISOTimeStamp(); + console.log(timestamp); + + const sendDiv = document.createElement('div'); + const paragraph = document.createElement('p'); + paragraph.setAttribute('style', `color: ${sendOrReceive === 'SEND' ? 'blue' : 'green'}`); + const paragraphContent = document.createTextNode( + `${timestamp} ${sendOrReceive === 'SEND' ? 'sent' : 'received'} >>> ${message}`, + ); + paragraph.appendChild(paragraphContent); + + sendDiv.appendChild(paragraph); + document.getElementById('output')?.appendChild(sendDiv); +}; + /** * Display messages that have been sent up the websocket. Colours them blue. * * @param {string} message */ -function displaySend(message: string) { - const timestamp = new Date().toISOString().substr(11, 12); - const sendDiv = document.createElement('div'); - const paragraph = document.createElement('p'); - paragraph.setAttribute('style', 'color: blue'); - const paragraphContent = document.createTextNode(`${timestamp} sent >>> ${message}`); - paragraph.appendChild(paragraphContent); - - sendDiv.appendChild(paragraph); - document.getElementById('output')?.appendChild(sendDiv); +export function displaySend(message: string) { + createChatEntry({ message, sendOrReceive: 'SEND' }); + return undefined; } /** @@ -38,24 +50,16 @@ function displaySend(message: string) { * * @param {string} message */ -export function displayReceived(message: string) { - const content = message; - const timestamp = new Date().toLocaleTimeString(); - const receivedDiv = document.createElement('div'); - const paragraph = document.createElement('p'); - paragraph.setAttribute('style', 'color: green'); - const paragraphContent = document.createTextNode(`${timestamp} received >>> ${content}`); - // const paragraphContent = document.createTextNode(timestamp + " received >>> " + content + ((replySurb != null) ? "Reply SURB was attached here (but we can't do anything with it yet" : " (NO REPLY-SURB AVAILABLE)")) - paragraph.appendChild(paragraphContent); - receivedDiv.appendChild(paragraph); - document.getElementById('output')?.appendChild(receivedDiv); +export function displayReceived(message: string) { + createChatEntry({ message, sendOrReceive: 'RECEIVE' }); + return undefined; } /** * Display the nymClient's sender address in the user interface * - * @param {Client} nymClient + * @param {string} address */ export function displaySenderAddress(address: string) { (document.getElementById('sender') as HTMLFormElement).value = address; diff --git a/sdk/typescript/examples/chat-app/parcel/src/index.ts b/sdk/typescript/examples/shared/index.ts similarity index 89% rename from sdk/typescript/examples/chat-app/parcel/src/index.ts rename to sdk/typescript/examples/shared/index.ts index 3871d1c0a7..16fffd3ac9 100644 --- a/sdk/typescript/examples/chat-app/parcel/src/index.ts +++ b/sdk/typescript/examples/shared/index.ts @@ -29,9 +29,9 @@ async function main() { displayReceived(e.args.payload); }); - const sendButton: HTMLButtonElement = document.querySelector('#send-button') as HTMLButtonElement; + const sendButton = document.querySelector('#send-button'); if (sendButton) { - sendButton.onclick = function () { + (sendButton as HTMLButtonElement).onclick = function () { if (nym) { sendMessageTo(nym); } diff --git a/sdk/typescript/packages/dom-utils/README.md b/sdk/typescript/packages/dom-utils/README.md new file mode 100644 index 0000000000..2cbde69fe2 --- /dev/null +++ b/sdk/typescript/packages/dom-utils/README.md @@ -0,0 +1,7 @@ +# Nym DOM Utils + +This package manipulates the DOM without any frameworks. + +## Usage + +TODO diff --git a/sdk/typescript/examples/chat-app/parcel/src/dom-utils.ts b/sdk/typescript/packages/dom-utils/index.ts similarity index 62% rename from sdk/typescript/examples/chat-app/parcel/src/dom-utils.ts rename to sdk/typescript/packages/dom-utils/index.ts index 7e98532ea3..cc7d70c6b3 100644 --- a/sdk/typescript/examples/chat-app/parcel/src/dom-utils.ts +++ b/sdk/typescript/packages/dom-utils/index.ts @@ -12,25 +12,32 @@ export async function sendMessageTo(nym: NymMixnetClient) { const recipient = (document.getElementById('recipient') as HTMLFormElement).value; await nym.client.send({ payload: { message, mimeType: MimeTypes.TextPlain }, recipient }); - displaySend(message); + createChatEntry({message, sendOrReceive: "SEND"}); } +const createISOTimeStamp = () => new Date().toISOString().substring(11, 12); + +const createChatEntry = ({message, sendOrReceive}: {message: string, sendOrReceive: "SEND" | "RECEIVE"}) => { + const timestamp = createISOTimeStamp(); + + const sendDiv = document.createElement('div'); + const paragraph = document.createElement('p'); + paragraph.setAttribute('style', `color: ${sendOrReceive === "SEND" ? "blue" : "green"}`); + const paragraphContent = document.createTextNode(`${timestamp} sent >>> ${message}`); + paragraph.appendChild(paragraphContent); + + sendDiv.appendChild(paragraph); + document.getElementById('output')?.appendChild(sendDiv); + /** * Display messages that have been sent up the websocket. Colours them blue. * * @param {string} message */ + function displaySend(message: string) { - const timestamp = new Date().toISOString().substr(11, 12); - - const sendDiv = document.createElement('div'); - const paragraph = document.createElement('p'); - paragraph.setAttribute('style', 'color: blue'); - const paragraphContent = document.createTextNode(`${timestamp} sent >>> ${message}`); - paragraph.appendChild(paragraphContent); - - sendDiv.appendChild(paragraph); - document.getElementById('output')?.appendChild(sendDiv); + createChatEntry({message, sendOrReceive: "SEND"}); + return undefined } /** @@ -38,18 +45,10 @@ function displaySend(message: string) { * * @param {string} message */ -export function displayReceived(message: string) { - const content = message; - const timestamp = new Date().toLocaleTimeString(); - const receivedDiv = document.createElement('div'); - const paragraph = document.createElement('p'); - paragraph.setAttribute('style', 'color: green'); - const paragraphContent = document.createTextNode(`${timestamp} received >>> ${content}`); - // const paragraphContent = document.createTextNode(timestamp + " received >>> " + content + ((replySurb != null) ? "Reply SURB was attached here (but we can't do anything with it yet" : " (NO REPLY-SURB AVAILABLE)")) - paragraph.appendChild(paragraphContent); - receivedDiv.appendChild(paragraph); - document.getElementById('output')?.appendChild(receivedDiv); +export function displayReceived(message: string) { + return createChatEntry({message, sendOrReceive: "RECEIVE"}); + return undefined } /** diff --git a/sdk/typescript/packages/mix-fetch/.babelrc b/sdk/typescript/packages/mix-fetch/.babelrc new file mode 100644 index 0000000000..0ef5ffc214 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@babel/env"] +} diff --git a/sdk/typescript/packages/mix-fetch/.gitignore b/sdk/typescript/packages/mix-fetch/.gitignore new file mode 100644 index 0000000000..71c42dc754 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/.gitignore @@ -0,0 +1,2 @@ +src/worker/*.js +docs diff --git a/sdk/typescript/packages/mix-fetch/README-CommonJS-full-fat.md b/sdk/typescript/packages/mix-fetch/README-CommonJS-full-fat.md new file mode 100644 index 0000000000..d22f063aeb --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/README-CommonJS-full-fat.md @@ -0,0 +1,16 @@ +# Nym MixFetch + +This package is a drop-in replacement for `fetch` to send HTTP requests over the Nym Mixnet. + +## Usage + +```js +const { createMixFetch } = require('@nymproject/mix-fetch'); + +... + +const mixFetch = await createMixFetch(); + +const response = await mixFetch('https://nymtech.net'); +const html = await response.text(); +``` diff --git a/sdk/typescript/packages/mix-fetch/README-CommonJS.md b/sdk/typescript/packages/mix-fetch/README-CommonJS.md new file mode 100644 index 0000000000..d22f063aeb --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/README-CommonJS.md @@ -0,0 +1,16 @@ +# Nym MixFetch + +This package is a drop-in replacement for `fetch` to send HTTP requests over the Nym Mixnet. + +## Usage + +```js +const { createMixFetch } = require('@nymproject/mix-fetch'); + +... + +const mixFetch = await createMixFetch(); + +const response = await mixFetch('https://nymtech.net'); +const html = await response.text(); +``` diff --git a/sdk/typescript/packages/mix-fetch/README-full-fat.md b/sdk/typescript/packages/mix-fetch/README-full-fat.md new file mode 100644 index 0000000000..abb83e2a20 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/README-full-fat.md @@ -0,0 +1,16 @@ +# Nym MixFetch + +This package is a drop-in replacement for `fetch` to send HTTP requests over the Nym Mixnet. + +## Usage + +```js +import { createMixFetch } from '@nymproject/mix-fetch'; + +... + +const mixFetch = await createMixFetch(); + +const response = await mixFetch('https://nymtech.net'); +const html = await response.text(); +``` diff --git a/sdk/typescript/packages/mix-fetch/README.md b/sdk/typescript/packages/mix-fetch/README.md new file mode 100644 index 0000000000..8772e69ffd --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/README.md @@ -0,0 +1,19 @@ +# Nym MixFetch + +This package is a drop-in replacement for `fetch` to send HTTP requests over the Nym Mixnet. + +## Usage + +Use `mixFetch` in your own project with: + +```js +import { createMixFetch } from '@nymproject/mix-fetch'; + +... + +const mixFetch = await createMixFetch(); + +const response = await mixFetch('https://nymtech.net'); +const html = await response.text(); +``` + diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/README.md b/sdk/typescript/packages/mix-fetch/internal-dev/README.md new file mode 100644 index 0000000000..21c25c7d90 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/internal-dev/README.md @@ -0,0 +1,44 @@ +# MixFetch Internal Tester + +This project is for use by Nym developers only. Use at your own risk! + +## Getting started + +From the root of this repository run: + +``` +yarn +make sdk-wasm-build +``` + +Then: + +``` +cd sdk/typescript/packages/mix-fetch +``` + +You can run in watch mode: + +``` +yarn start +``` + +Or do a single build: + +``` +yarn build:dev:esm +``` + +Then, in another terminal: + +``` +cd sdk/typescript/packages/mix-fetch/internal-dev/parcel +yarn && yarn start +``` + +If you have trouble with changes not propagating: + +``` +rm -rf node_modules && yarn && yarn start +``` + diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/package.json b/sdk/typescript/packages/mix-fetch/internal-dev/package.json new file mode 100644 index 0000000000..549143b0d1 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/internal-dev/package.json @@ -0,0 +1,57 @@ +{ + "name": "@nymproject/mix-fetch-tester-webpack", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@nymproject/mix-fetch": ">=1.2.0-rc.2 || ^1" + }, + "devDependencies": { + "@babel/core": "^7.22.10", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/preset-env": "^7.22.10", + "@babel/preset-typescript": "^7.22.5", + "@types/jest": "^27.0.1", + "@types/node": "^16.7.13", + "@typescript-eslint/eslint-plugin": "^5.13.0", + "@typescript-eslint/parser": "^5.13.0", + "babel-loader": "^9.1.3", + "babel-plugin-root-import": "^6.6.0", + "clean-webpack-plugin": "^4.0.0", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.8.1", + "css-minimizer-webpack-plugin": "^5.0.1", + "dotenv-webpack": "^8.0.1", + "eslint": "^8.10.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-airbnb-typescript": "^16.1.0", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-root-import": "^1.0.4", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^26.1.1", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-prettier": "^4.0.0", + "file-loader": "^6.2.0", + "fork-ts-checker-webpack-plugin": "^8.0.0", + "html-webpack-plugin": "^5.5.3", + "jest": "^27.1.0", + "mini-css-extract-plugin": "^2.7.6", + "npm-run-all": "^4.1.5", + "prettier": "^2.8.7", + "style-loader": "^3.3.3", + "thread-loader": "^4.0.2", + "ts-jest": "^27.0.5", + "ts-loader": "^9.4.4", + "tsconfig-paths-webpack-plugin": "^4.1.0", + "typescript": "^4.6.2", + "url-loader": "^4.1.1", + "webpack": "^5.88.2", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^4.15.1", + "webpack-merge": "^5.9.0" + }, + "scripts": { + "start": "webpack serve --progress --port 3000", + "build": "webpack build --progress --config webpack.prod.js", + "serve": "npx serve dist" + } +} diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json b/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json new file mode 100644 index 0000000000..d0ae96d225 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json @@ -0,0 +1,14 @@ +{ + "name": "@nymproject/mix-fetch-tester-parcel", + "version": "1.0.0", + "license": "Apache-2.0", + "source": "../src/index.html", + "dependencies": { + "@nymproject/mix-fetch": ">=1.2.0-rc.2 || ^1" + }, + "scripts": { + "start": "npx parcel --no-cache", + "build": "npx parcel build --no-cache --no-content-hash", + "serve": "npx serve dist" + } +} diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/src/index.html b/sdk/typescript/packages/mix-fetch/internal-dev/src/index.html new file mode 100644 index 0000000000..7ed4ee38f4 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/internal-dev/src/index.html @@ -0,0 +1,18 @@ + + + + + + + Internal Tester + + + + +

Internal tester

+

Open dev tools to see more output and errors

+

+
+ + + diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/src/index.ts b/sdk/typescript/packages/mix-fetch/internal-dev/src/index.ts new file mode 100644 index 0000000000..d6804dbd4d --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/internal-dev/src/index.ts @@ -0,0 +1,72 @@ +import { createMixFetch } from '@nymproject/mix-fetch'; + +function appendOutput(value: string) { + const el = document.getElementById('output') as HTMLPreElement; + const text = document.createTextNode(`${value}\n`); + el.appendChild(text); +} + +function appendImageOutput(url: string) { + const el = document.getElementById('outputImage') as HTMLPreElement; + const imgNode = document.createElement('img'); + imgNode.src = url; + el.appendChild(imgNode); +} + +/** + * The main entry point + */ +async function main() { + appendOutput('Tester is starting up...'); + + // const addr = + // 'EVdJ66jqpoVzmktVecy5UJxsTCEWo5gMn5zDZR7Hm8jy.GXNpoX7RcYcxKvBkV3dSHqC78WaPuWieweRPWzYqNhh5@GAjhJcrd6f1edaqUkfWCff6zdHoqo756qYrc2TfPuCXJ'; + const addr = undefined; + + appendOutput('About to set up mixFetch...'); + const { mixFetch } = await createMixFetch({ + preferredNetworkRequester: addr, + clientId: 'my-new-client-16', + clientOverride: { + coverTraffic: { disableLoopCoverTrafficStream: true }, + traffic: { disableMainPoissonPacketDistribution: true }, + }, + mixFetchOverride: { requestTimeoutMs: 60000 }, + responseBodyConfigMap: {}, + }); + (window as any).mixFetch = mixFetch; + + if (!(window as any).mixFetch) { + console.error('Oh no! Could not create mixFetch'); + appendOutput('Oh no! Could not create mixFetch'); + } else { + appendOutput('Ready!'); + } + + let url = 'https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt'; + appendOutput(`Using mixFetch to get ${url}...`); + const args = { mode: 'unsafe-ignore-cors' }; + + let resp = await mixFetch(url, args); + console.log({ resp }); + const text = await resp.text(); + + appendOutput(JSON.stringify(resp, null, 2)); + appendOutput(JSON.stringify({ text }, null, 2)); + + // get an image + url = 'https://nymtech.net/images/token/pie-classic-2.svg'; + resp = await mixFetch(url, args); + console.log({ resp }); + const buffer = await resp.arrayBuffer(); + const type = resp.headers.get('Content-Type') || 'image/svg'; + const blobUrl = URL.createObjectURL(new Blob([buffer], { type })); + appendOutput(JSON.stringify({ bufferBytes: buffer.byteLength, blobUrl }, null, 2)); + appendImageOutput(blobUrl); +} + +// wait for the html to load +window.addEventListener('DOMContentLoaded', () => { + // let's do this! + main(); +}); diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/tsconfig.json b/sdk/typescript/packages/mix-fetch/internal-dev/tsconfig.json new file mode 100644 index 0000000000..4fdd59edbb --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/internal-dev/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "module": "ESNext", + "outDir": "./dist" + }, + "exclude": ["node_modules", "build", "dist"] +} diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/webpack.common.js b/sdk/typescript/packages/mix-fetch/internal-dev/webpack.common.js new file mode 100644 index 0000000000..200d2ab28e --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/internal-dev/webpack.common.js @@ -0,0 +1,45 @@ +const path = require('path'); +const { mergeWithRules } = require('webpack-merge'); +const CopyPlugin = require('copy-webpack-plugin'); +const { webpackCommon } = require('../../../examples/.webpack/webpack.base'); + +console.log('mix-fetch package path is: ', path.dirname(require.resolve('@nymproject/mix-fetch/package.json'))); + +module.exports = mergeWithRules({ + module: { + rules: { + test: 'match', + use: 'replace', + }, + }, +})( + webpackCommon(__dirname, [ + { + inject: true, + filename: 'index.html', + template: path.resolve(__dirname, 'src/index.html'), + chunks: ['index'], + }, + ]), + { + entry: { + index: path.resolve(__dirname, 'src/index.ts'), + }, + output: { + path: path.resolve(__dirname, 'dist'), + publicPath: '/', + }, + plugins: [ + new CopyPlugin({ + patterns: [ + { + // copy the WASM files, because webpack doesn't do this automatically even though there are + // `new URL(..., import.meta.url)` statements in the web worker + from: path.resolve(path.dirname(require.resolve('@nymproject/mix-fetch/package.json')), 'dist/esm/*.wasm'), + to: '[name][ext]', + }, + ], + }), + ], + }, +); diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/webpack.config.js b/sdk/typescript/packages/mix-fetch/internal-dev/webpack.config.js new file mode 100644 index 0000000000..085b2eac55 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/internal-dev/webpack.config.js @@ -0,0 +1,71 @@ +const { mergeWithRules } = require('webpack-merge'); +const webpack = require('webpack'); +const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); +const ReactRefreshTypeScript = require('react-refresh-typescript'); +const commonConfig = require('./webpack.common'); + +module.exports = mergeWithRules({ + module: { + rules: { + test: 'match', + use: 'replace', + }, + }, +})(commonConfig, { + mode: 'development', + devtool: 'inline-source-map', + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/, + options: { + getCustomTransformers: () => ({ + before: [ReactRefreshTypeScript()], + }), + // `ts-loader` does not work with HMR unless `transpileOnly` is used. + // If you need type checking, `ForkTsCheckerWebpackPlugin` is an alternative. + transpileOnly: true, + }, + }, + { + test: /\.wasm$/i, + type: 'asset/resource', + }, + ], + }, + plugins: [ + new ReactRefreshWebpackPlugin(), + + // this can be included automatically by the dev server, however build mode fails if missing + new webpack.HotModuleReplacementPlugin(), + ], + + target: 'web', + + devServer: { + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization', + }, + historyApiFallback: true, + }, + + // recommended for faster rebuild + optimization: { + runtimeChunk: true, + removeAvailableModules: false, + removeEmptyChunks: false, + splitChunks: false, + }, + + cache: { + type: 'filesystem', + buildDependencies: { + // restart on config change + config: ['./webpack.config.js'], + }, + }, +}); diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/webpack.prod.js b/sdk/typescript/packages/mix-fetch/internal-dev/webpack.prod.js new file mode 100644 index 0000000000..c92239179a --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/internal-dev/webpack.prod.js @@ -0,0 +1,42 @@ +const { mergeWithRules } = require('webpack-merge'); +const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const commonConfig = require('./webpack.common'); + +module.exports = mergeWithRules({ + module: { + rules: { + test: 'match', + use: 'replace', + }, + }, +})(commonConfig, { + mode: 'production', + + // TODO: no source maps, add back + devtool: false, + + module: { + rules: [ + { + test: /\.css$/, + use: [MiniCssExtractPlugin.loader, 'css-loader'], + }, + ], + }, + optimization: { + minimizer: ['...', new CssMinimizerPlugin()], + splitChunks: { + chunks: 'all', + }, + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: '[name].[contenthash].css', + }), + ], + output: { + pathinfo: false, + filename: '[name].[contenthash].js', + }, +}); diff --git a/sdk/typescript/packages/mix-fetch/jest.config.mjs b/sdk/typescript/packages/mix-fetch/jest.config.mjs new file mode 100644 index 0000000000..ed5b112c72 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/jest.config.mjs @@ -0,0 +1,15 @@ +import preset from 'ts-jest/presets/index.js' + +/** @type {import('ts-jest').JestConfigWithTsJest} */ +export default { + ...preset.defaults, + transform: { + '^.+\\.(ts|tsx)$': [ + 'ts-jest', + { + tsconfig: 'tsconfig.jest.json', + useESM: true, + }, + ], + }, +} diff --git a/sdk/typescript/packages/mix-fetch/package.json b/sdk/typescript/packages/mix-fetch/package.json new file mode 100644 index 0000000000..e5779983e3 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/package.json @@ -0,0 +1,83 @@ +{ + "name": "@nymproject/mix-fetch", + "version": "1.2.0-rc.2", + "description": "This package is a drop-in replacement for `fetch` to send HTTP requests over the Nym Mixnet.", + "license": "Apache-2.0", + "author": "Nym Technologies SA", + "files": [ + "dist/esm/worker.js", + "dist/cjs/worker.js", + "dist/**/*" + ], + "main": "dist/cjs/index.js", + "browser": "dist/esm/index.js", + "scripts": { + "build": "scripts/build-prod.sh", + "build:dev": "scripts/build.sh", + "build:dev:esm": "MIX_FETCH_DEV_MODE=true scripts/build-dev-esm.sh", + "build:dev:esm-no-inline": "scripts/build-dev-esm.sh", + "build:worker": "rollup -c rollup-worker.config.mjs", + "clean": "rimraf dist", + "docs:dev": "run-p docs:watch docs:serve ", + "docs:generate": "typedoc", + "docs:generate:prod": "typedoc --basePath ./docs/tsdoc/nymproject/sdk/", + "docs:prod:build": "scripts/build-prod-docs-collect.sh", + "docs:serve": "reload -b -d ./docs -p 3000", + "docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\"", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "tsc -w", + "start:dev": "nodemon --watch src -e ts,json --exec 'yarn build:dev:esm'", + "test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache", + "tsc": "tsc --noEmit true" + }, + "dependencies": { + "@nymproject/mix-fetch-wasm": ">=1.2.0-rc.0 || 1", + "comlink": "^4.3.1" + }, + "devDependencies": { + "@babel/core": "^7.15.0", + "@babel/plugin-transform-async-to-generator": "^7.14.5", + "@babel/preset-env": "^7.15.0", + "@babel/preset-react": "^7.14.5", + "@babel/preset-typescript": "^7.15.0", + "@nymproject/eslint-config-react-typescript": "^1.0.0", + "@rollup/plugin-commonjs": "^24.0.1", + "@rollup/plugin-inject": "^5.0.3", + "@rollup/plugin-json": "^6.0.0", + "@rollup/plugin-node-resolve": "^15.0.1", + "@rollup/plugin-replace": "^5.0.2", + "@rollup/plugin-terser": "^0.2.1", + "@rollup/plugin-typescript": "^10.0.1", + "@rollup/plugin-wasm": "^6.1.1", + "@types/jest": "^27.0.1", + "@types/node": "^16.7.13", + "@typescript-eslint/eslint-plugin": "^5.13.0", + "@typescript-eslint/parser": "^5.13.0", + "eslint": "^8.10.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-airbnb-typescript": "^16.1.0", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-root-import": "^1.0.4", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^26.1.1", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-react": "^7.29.2", + "eslint-plugin-react-hooks": "^4.3.0", + "jest": "^29.5.0", + "nodemon": "^2.0.21", + "reload": "^3.2.1", + "rimraf": "^3.0.2", + "rollup": "^3.9.1", + "rollup-plugin-base64": "^1.0.1", + "rollup-plugin-web-worker-loader": "^1.6.1", + "ts-jest": "^29.1.0", + "ts-loader": "^9.4.2", + "typedoc": "^0.24.8", + "typescript": "^4.8.4" + }, + "private": false, + "type": "module", + "types": "./dist/esm/index.d.ts" +} diff --git a/sdk/typescript/packages/mix-fetch/rollup-cjs-full-fat.config.mjs b/sdk/typescript/packages/mix-fetch/rollup-cjs-full-fat.config.mjs new file mode 100644 index 0000000000..d4c6e39e99 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/rollup-cjs-full-fat.config.mjs @@ -0,0 +1,8 @@ +import { getConfig } from './rollup/cjs.mjs'; + +export default { + ...getConfig({ + inline: true, + outputDir: 'dist/cjs-full-fat', + }), +}; diff --git a/sdk/typescript/packages/mix-fetch/rollup-cjs.config.mjs b/sdk/typescript/packages/mix-fetch/rollup-cjs.config.mjs new file mode 100644 index 0000000000..a12e5bdb7a --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/rollup-cjs.config.mjs @@ -0,0 +1,5 @@ +import { getConfig } from './rollup/cjs.mjs'; + +export default { + ...getConfig({ inline: false }), +}; diff --git a/sdk/typescript/packages/mix-fetch/rollup-esm-full-fat.config.mjs b/sdk/typescript/packages/mix-fetch/rollup-esm-full-fat.config.mjs new file mode 100644 index 0000000000..ea80b1997b --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/rollup-esm-full-fat.config.mjs @@ -0,0 +1,8 @@ +import { getConfig } from './rollup/esm.mjs'; + +export default { + ...getConfig({ + inline: true, + outputDir: 'dist/esm-full-fat', + }), +}; diff --git a/sdk/typescript/packages/mix-fetch/rollup-esm.config.mjs b/sdk/typescript/packages/mix-fetch/rollup-esm.config.mjs new file mode 100644 index 0000000000..fe7b0082bb --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/rollup-esm.config.mjs @@ -0,0 +1,8 @@ +import { getConfig } from './rollup/esm.mjs'; + +export default { + ...getConfig({ + // by default, the web worker will not be inlined, in local development mode it will be + inline: process.env.MIX_FETCH_DEV_MODE === 'true', + }), +}; diff --git a/sdk/typescript/packages/mix-fetch/rollup-worker-new.config.mjs b/sdk/typescript/packages/mix-fetch/rollup-worker-new.config.mjs new file mode 100644 index 0000000000..54d6fd774b --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/rollup-worker-new.config.mjs @@ -0,0 +1,37 @@ +import typescript from '@rollup/plugin-typescript'; +import resolve from '@rollup/plugin-node-resolve'; +import { wasm } from '@rollup/plugin-wasm'; +import replace from '@rollup/plugin-replace'; + +const extensions = ['.js', '.jsx', '.ts', '.tsx']; + +export default { + input: 'src/worker/index.ts', + output: { + dir: 'dist', + format: process.env.MIX_FETCH_BUNDLE_INLINE_WORKER === true ? 'cjs' : 'es', + // format: 'cjs', + }, + plugins: [ + resolve({ extensions }), + // this is some nasty monkey patching that removes the WASM URL (because it is handled by the `wasm` plugin) + replace({ + values: { "input = new URL('mix_fetch_wasm_bg.wasm', import.meta.url);": 'input = undefined;' }, + delimiters: ['', ''], + preventAssignment: true, + }), + wasm({ + targetEnv: 'browser', + fileName: '[name].wasm', + // force the wasm plugin to embed the wasm bundle - this means no downstream bundlers have to worry about handling it + maxFileSize: process.env.MIX_FETCH_BUNDLE_INLINE_WASM === 'true' ? 10000000 : undefined, + }), + typescript({ + compilerOptions: { + declaration: false, + target: process.env.MIX_FETCH_BUNDLE_INLINE_WORKER === true ? 'es5' : 'es6', + // target: 'es5', + }, + }), + ], +}; diff --git a/sdk/typescript/packages/mix-fetch/rollup-worker.config.mjs b/sdk/typescript/packages/mix-fetch/rollup-worker.config.mjs new file mode 100644 index 0000000000..54d6fd774b --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/rollup-worker.config.mjs @@ -0,0 +1,37 @@ +import typescript from '@rollup/plugin-typescript'; +import resolve from '@rollup/plugin-node-resolve'; +import { wasm } from '@rollup/plugin-wasm'; +import replace from '@rollup/plugin-replace'; + +const extensions = ['.js', '.jsx', '.ts', '.tsx']; + +export default { + input: 'src/worker/index.ts', + output: { + dir: 'dist', + format: process.env.MIX_FETCH_BUNDLE_INLINE_WORKER === true ? 'cjs' : 'es', + // format: 'cjs', + }, + plugins: [ + resolve({ extensions }), + // this is some nasty monkey patching that removes the WASM URL (because it is handled by the `wasm` plugin) + replace({ + values: { "input = new URL('mix_fetch_wasm_bg.wasm', import.meta.url);": 'input = undefined;' }, + delimiters: ['', ''], + preventAssignment: true, + }), + wasm({ + targetEnv: 'browser', + fileName: '[name].wasm', + // force the wasm plugin to embed the wasm bundle - this means no downstream bundlers have to worry about handling it + maxFileSize: process.env.MIX_FETCH_BUNDLE_INLINE_WASM === 'true' ? 10000000 : undefined, + }), + typescript({ + compilerOptions: { + declaration: false, + target: process.env.MIX_FETCH_BUNDLE_INLINE_WORKER === true ? 'es5' : 'es6', + // target: 'es5', + }, + }), + ], +}; diff --git a/sdk/typescript/packages/mix-fetch/rollup/cjs.mjs b/sdk/typescript/packages/mix-fetch/rollup/cjs.mjs new file mode 100644 index 0000000000..4f76b89648 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/rollup/cjs.mjs @@ -0,0 +1,30 @@ +import typescript from '@rollup/plugin-typescript'; +import resolve from '@rollup/plugin-node-resolve'; +import { wasm } from '@rollup/plugin-wasm'; +import webWorkerLoader from 'rollup-plugin-web-worker-loader'; + +const extensions = ['.js', '.jsx', '.ts', '.tsx']; + +/** + * Gets the config for bundling the package as a CommonJS module. + * + * @param opts Options: + * `{ inline: boolean }` - set inline to true to inline the web worker in the main bundle + * `{ outputDir: string }` - override the destination + */ +export const getConfig = (opts) => ({ + input: 'src/index.ts', + output: { + dir: opts.outputDir || 'dist/cjs', + format: 'cjs', + }, + plugins: [ + webWorkerLoader({ targetPlatform: 'browser', inline: opts.inline }), // the inline param is used here + resolve({ extensions }), + wasm({ maxFileSize: 10000000, targetEnv: 'browser' }), + typescript({ + compilerOptions: { outDir: opts.outputDir || 'dist/cjs', target: 'es5' }, + exclude: ['worker/*'], + }), + ], +}); diff --git a/sdk/typescript/packages/mix-fetch/rollup/esm.mjs b/sdk/typescript/packages/mix-fetch/rollup/esm.mjs new file mode 100644 index 0000000000..e2b5efea66 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/rollup/esm.mjs @@ -0,0 +1,41 @@ +import typescript from '@rollup/plugin-typescript'; +import resolve from '@rollup/plugin-node-resolve'; +import webWorkerLoader from 'rollup-plugin-web-worker-loader'; +import replace from '@rollup/plugin-replace'; + +const extensions = ['.js', '.jsx', '.ts', '.tsx']; + +/** + * Gets the config for bundling the package as an ES Module. + * + * @param opts Options: + * `{ inline: boolean }` - set inline to true to inline the web worker in the main bundle + * `{ outputDir: string }` - override the destination * + */ +export const getConfig = (opts) => ({ + input: 'src/index.ts', + output: { + dir: opts.outputDir || 'dist/esm', + format: 'es', + }, + plugins: [ + webWorkerLoader({ targetPlatform: 'browser', inline: opts.inline }), // the inline param is used here + replace({ + // when loading the web worker as a full ES module, tell pass `new Worker({ type: 'module'})` to tell + // the browser to load and allow imports inside the worker code. Also load as a URL so relative paths work. + values: opts.inline + ? undefined + : { + "createURLWorkerFactory('web-worker-0.js')": + "createURLWorkerFactory(new URL('web-worker-0.js', import.meta.url))", + }, + delimiters: ['', ''], + preventAssignment: true, + }), + resolve({ extensions }), + typescript({ + exclude: ['worker/*'], + compilerOptions: { outDir: opts.outputDir || 'dist/esm' }, + }), + ], +}); diff --git a/sdk/typescript/packages/mix-fetch/scripts/build-dev-esm.sh b/sdk/typescript/packages/mix-fetch/scripts/build-dev-esm.sh new file mode 100755 index 0000000000..60ffc7e90f --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/scripts/build-dev-esm.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +#------------------------------------------------------- +# WEB WORKER (mix-fetch WASM) +#------------------------------------------------------- +# The web worker needs to be bundled because the WASM bundle needs to be loaded synchronously and all dependencies +# must be included in the worker script (because it is not loaded as an ES Module) + +# build the worker +rollup -c rollup-worker.config.mjs + +# move it next to the Typescript `src/index.ts` so it can be inlined by rollup +rm -f src/worker/*.js +rm -f src/worker/*.wasm +mv dist/index.js src/worker/worker.js + +# move WASM files out of build area +mkdir -p dist/worker +mv dist/*.wasm dist/worker + +#------------------------------------------------------- +# ESM +#------------------------------------------------------- + +# build the SDK as a ESM bundle +rollup -c rollup-esm.config.mjs + +# move WASM files into place +cp dist/worker/*.wasm dist/esm +node scripts/postBuildReplace.mjs dist + +#------------------------------------------------------- +# CLEAN UP +#------------------------------------------------------- + +# remove typings that aren't needed +rm -rf dist/esm/worker + +# clear staging area +rm -rf dist/worker + + diff --git a/sdk/typescript/packages/mix-fetch/scripts/build-prod-docs-collect.sh b/sdk/typescript/packages/mix-fetch/scripts/build-prod-docs-collect.sh new file mode 100755 index 0000000000..f672185300 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/scripts/build-prod-docs-collect.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf ../../../../dist/ts/docs/tsdoc/nymproject/mix-fetch || true + +# run the build +yarn docs:generate:prod + +# move the output outside of the yarn/npm workspaces +mkdir -p ../../../../dist/ts/docs/tsdoc/nymproject +mv docs ../../../../dist/ts/docs/tsdoc/nymproject/mix-fetch + +echo "Output can be found in:" +realpath ../../../../dist/ts/docs/tsdoc/nymproject/mix-fetch diff --git a/sdk/typescript/packages/mix-fetch/scripts/build-prod.sh b/sdk/typescript/packages/mix-fetch/scripts/build-prod.sh new file mode 100755 index 0000000000..b56d1e0472 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/scripts/build-prod.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf dist || true +rm -rf ../../../../dist/ts/sdk/mix-fetch || true + +# run the build +scripts/build.sh +node scripts/buildPackageJson.mjs + +# move the output outside of the yarn/npm workspaces +mkdir -p ../../../../dist/ts/sdk +mv dist ../../../../dist/ts/sdk +mv ../../../../dist/ts/sdk/dist ../../../../dist/ts/sdk/mix-fetch + +echo "Output can be found in:" +realpath ../../../../dist/ts/sdk/mix-fetch diff --git a/sdk/typescript/packages/mix-fetch/scripts/build.sh b/sdk/typescript/packages/mix-fetch/scripts/build.sh new file mode 100755 index 0000000000..14aeba0085 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/scripts/build.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf dist || true + +#------------------------------------------------------- +# WEB WORKER (mix-fetch WASM) +#------------------------------------------------------- +# The web worker needs to be bundled because the WASM bundle needs to be loaded synchronously and all dependencies +# must be included in the worker script (because it is not loaded as an ES Module) + +# build the worker +rollup -c rollup-worker.config.mjs + +# move it next to the Typescript `src/index.ts` so it can be inlined by rollup +rm -f src/worker/*.js +rm -f src/worker/*.wasm +mv dist/index.js src/worker/worker.js + +# move WASM files out of build area +mkdir -p dist/worker +mv dist/*.wasm dist/worker + +#------------------------------------------------------- +# ESM +#------------------------------------------------------- + +# build the SDK as a ESM bundle +rollup -c rollup-esm.config.mjs + +#------------------------------------------------------- +# COMMON JS +#------------------------------------------------------- +# Some old build systems cannot fully handle ESM or ES2021, so build +# a CommonJS bundle targeting ES5 + +# build the SDK as a CommonJS bundle +rollup -c rollup-cjs.config.mjs + +# move WASM files into place +cp dist/worker/*.wasm dist/esm +node scripts/postBuildReplace.mjs dist + +#------------------------------------------------------- +# ESM (full-fat) +#------------------------------------------------------- + +# build the SDK as a ESM bundle (with worker inlined as a blob) +rollup -c rollup-esm-full-fat.config.mjs + +#------------------------------------------------------- +# COMMON JS (full-fat) +#------------------------------------------------------- +# Some old build systems cannot fully handle ESM or ES2021, so build +# a CommonJS bundle targeting ES5 + +# build the SDK as a CommonJS bundle (with worker inlined as a blob) +rollup -c rollup-cjs-full-fat.config.mjs + +#------------------------------------------------------- +# CLEAN UP +#------------------------------------------------------- + +rm -rf dist/cjs/worker +rm -rf dist/esm/worker +rm -rf dist/cjs-full-fat/worker +rm -rf dist/esm-full-fat/worker + +# copy README +cp README.md dist/esm +cp README-CommonJS.md dist/cjs/README.md +cp README-CommonJS-full-fat.md dist/cjs-full-fat/README.md +cp README-full-fat.md dist/esm-full-fat/README.md + + diff --git a/sdk/typescript/packages/mix-fetch/scripts/buildPackageJson.mjs b/sdk/typescript/packages/mix-fetch/scripts/buildPackageJson.mjs new file mode 100644 index 0000000000..3fc5a7b5b2 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/scripts/buildPackageJson.mjs @@ -0,0 +1,29 @@ +import * as fs from 'fs'; + +// parse the package.json from the SDK, so we can keep fields like the name and version +const json = JSON.parse(fs.readFileSync('package.json').toString()); + +// defaults (NB: these are in the output file locations) +const browser = 'index.js'; +const main = 'index.js'; +const types = 'index.d.ts'; + +const getPackageJson = (type, suffix) => ({ + name: `${json.name}${suffix ? `-${suffix}` : ''}`, + version: json.version, + license: json.license, + author: json.author, + type, + browser, + main, + types, +}); + +fs.writeFileSync('dist/cjs/package.json', JSON.stringify(getPackageJson('commonjs', 'commonjs'), null, 2)); +fs.writeFileSync('dist/esm/package.json', JSON.stringify(getPackageJson('module'), null, 2)); + +fs.writeFileSync( + 'dist/cjs-full-fat/package.json', + JSON.stringify(getPackageJson('commonjs', 'commonjs-full-fat'), null, 2), +); +fs.writeFileSync('dist/esm-full-fat/package.json', JSON.stringify(getPackageJson('module', 'full-fat'), null, 2)); diff --git a/sdk/typescript/packages/mix-fetch/scripts/postBuildReplace.mjs b/sdk/typescript/packages/mix-fetch/scripts/postBuildReplace.mjs new file mode 100644 index 0000000000..f3e307c96a --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/scripts/postBuildReplace.mjs @@ -0,0 +1,39 @@ +import fs from 'fs'; +import path from 'path'; + +// first level is a list of file names to process, then for each copying the @rollup/replace plugin syntax here: +// key is what to search for, value is what to replace it with +const replaceConfig = { + 'esm/web-worker-0.js': { + // add `import.meta.url` to make WASM file relative to the worker JS file + "_loadWasmModule(0, 'mix_fetch_wasm_bg.wasm',": + "_loadWasmModule(0, new URL('mix_fetch_wasm_bg.wasm', import.meta.url),", + "_loadWasmModule(0, 'go_conn.wasm',": "_loadWasmModule(0, new URL('go_conn.wasm', import.meta.url),", + }, + 'esm/index.js': { + // tell the browser the worker is a module, so it should provide `import.meta.url` needed above + 'const worker = new WorkerFactory();': "const worker = new WorkerFactory({ type: 'module' });", + }, +}; + +const basePathToFindFilesIn = process.argv[2]; + +console.log(`Replacing files in "${path.resolve(basePathToFindFilesIn)}"...`); + +Object.keys(replaceConfig).forEach((filename) => { + const absFilename = path.resolve(basePathToFindFilesIn, filename); + const content = fs.readFileSync(absFilename).toString(); + + console.log(`Replacing values in "${absFilename}"...`); + + const replacementMap = replaceConfig[filename]; + + let newContent = content; + Object.keys(replacementMap).forEach((toFind) => { + const toReplace = replacementMap[toFind]; + newContent = newContent.replaceAll(toFind, toReplace); + fs.writeFileSync(absFilename, newContent); + }); + + console.log('Done'); +}); diff --git a/sdk/typescript/packages/sdk/scripts/publish.sh b/sdk/typescript/packages/mix-fetch/scripts/publish.sh similarity index 100% rename from sdk/typescript/packages/sdk/scripts/publish.sh rename to sdk/typescript/packages/mix-fetch/scripts/publish.sh diff --git a/sdk/typescript/packages/mix-fetch/src/create-mix-fetch.ts b/sdk/typescript/packages/mix-fetch/src/create-mix-fetch.ts new file mode 100644 index 0000000000..d45b74704e --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/src/create-mix-fetch.ts @@ -0,0 +1,76 @@ +import InlineWasmWebWorker from 'web-worker:./worker/worker'; +import * as Comlink from 'comlink'; +import type { IMixFetchWebWorker } from './types'; +import { EventKinds, IMixFetch } from './types'; + +const createWorker = async () => + new Promise((resolve, reject) => { + // rollup will inline the built worker script, so that when the SDK is used in + // other projects, they will not need to mess around trying to bundle it + // however, it will make this SDK bundle bigger because of Base64 inline data + const worker = new InlineWasmWebWorker(); + + worker.addEventListener('error', reject); + worker.addEventListener( + 'message', + (msg) => { + worker.removeEventListener('error', reject); + if (msg.data?.kind === EventKinds.Loaded) { + resolve(worker); + } else { + reject(msg); + } + }, + { once: true }, + ); + }); + +const convertHeaders = (headers: any): Headers => { + const out = new Headers(); + Object.keys(headers).forEach((key) => { + out.append(key, headers[key]); + }); + return out; +}; + +/** + * Use this method to initialise `mixFetch`. + * + * @returns An instance of `mixFetch` that you can use to make your requests using the same interface as `fetch`. + */ +export const createMixFetch = async (): Promise => { + // start the worker + const worker = await createWorker(); + + // bind with Comlink + const wrappedWorker = Comlink.wrap(worker); + + // handle the responses + const mixFetchWebWorker: IMixFetch = { + setupMixFetch: wrappedWorker.setupMixFetch, + mixFetch: async (url: string, args: any) => { + const workerResponse = await wrappedWorker.mixFetch(url, args); + if (!workerResponse) { + throw new Error('No response received'); + } + console.log({ workerResponse }); + const { headers: headersRaw, status, statusText } = workerResponse; + + // reconstruct the Headers object instance from a plain object + const headers = convertHeaders(headersRaw); + + // handle blobs + if (workerResponse.body.blobUrl) { + const blob = await (await fetch(workerResponse.body.blobUrl)).blob(); + const body = await blob.arrayBuffer(); + return new Response(body, { headers, status, statusText }); + } + + // handle everything else + const body = Object.values(workerResponse.body)[0]; // we are expecting only one value to be set in `.body` + return new Response(body, { headers, status, statusText }); + }, + }; + + return mixFetchWebWorker; +}; diff --git a/sdk/typescript/packages/mix-fetch/src/index.ts b/sdk/typescript/packages/mix-fetch/src/index.ts new file mode 100644 index 0000000000..701b30daa6 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/src/index.ts @@ -0,0 +1,42 @@ +/* eslint-disable no-underscore-dangle */ +import type { SetupMixFetchOps, IMixFetchFn, IMixFetch } from './types'; +import { createMixFetch as createMixFetchInternal } from './create-mix-fetch'; + +export * from './types'; + +declare global { + interface Window { + /** + * Keep a singleton of the mixFetch interface on the `window` object. + */ + __mixFetchGlobal?: IMixFetch; + } +} + +/** + * Create a global mixFetch instance and optionally configure settings. + * + * @param opts Optional settings + */ +export const createMixFetch = async (opts?: SetupMixFetchOps) => { + if (!window.__mixFetchGlobal) { + // load the worker and set up mixFetch with defaults + window.__mixFetchGlobal = await createMixFetchInternal(); + await window.__mixFetchGlobal.setupMixFetch(opts); + } + return window.__mixFetchGlobal; +}; + +/** + * mixFetch is a drop-in replacement for the standard `fetch` interface. + * + * @param url The URL to fetch from. + * @param args Fetch options. + */ +export const mixFetch: IMixFetchFn = async (url, args) => { + // ensure mixFetch instance exists + const instance = await createMixFetch(); + + // execute user request + return instance.mixFetch(url, args); +}; diff --git a/sdk/typescript/packages/mix-fetch/src/types.ts b/sdk/typescript/packages/mix-fetch/src/types.ts new file mode 100644 index 0000000000..56aa56cb96 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/src/types.ts @@ -0,0 +1,96 @@ +import type { MixFetchOpts } from '@nymproject/mix-fetch-wasm'; + +type IMixFetchWorkerFn = (url: string, args: any) => Promise; + +// export type IMixFetchFn = typeof fetch; +export type IMixFetchFn = (url: string, args: any) => Promise; + +export type SetupMixFetchOps = MixFetchOpts & { + responseBodyConfigMap?: ResponseBodyConfigMap; +}; + +export interface IMixFetchWebWorker { + mixFetch: IMixFetchWorkerFn; + setupMixFetch: (opts?: SetupMixFetchOps) => Promise; +} + +export interface IMixFetch { + mixFetch: IMixFetchFn; + setupMixFetch: (opts?: SetupMixFetchOps) => Promise; +} + +export enum EventKinds { + Loaded = 'Loaded', +} + +export interface LoadedEvent { + kind: EventKinds.Loaded; + args: { + loaded: true; + }; +} + +export interface ResponseBody { + uint8array?: Uint8Array; + json?: any; + text?: string; + formData?: any; + blobUrl?: string; +} + +export type ResponseBodyMethod = 'uint8array' | 'json' | 'text' | 'formData' | 'blob'; + +export interface ResponseBodyConfigMap { + /** + * Set the response `Content-Type`s to decode as uint8array. + */ + uint8array?: Array; + + /** + * Set the response `Content-Type`s to decode with the `json()` response body method. + */ + json?: Array; + + /** + * Set the response `Content-Type`s to decode with the `text()` response body method. + */ + text?: Array; + + /** + * Set the response `Content-Type`s to decode with the `formData()` response body method. + */ + formData?: Array; + + /** + * Set the response `Content-Type`s to decode with the `blob()` response body method. + */ + blob?: Array; + /** + * Set this to the default fallback method. Set to `undefined` if you want to ignore unknown types. + */ + + fallback?: ResponseBodyMethod; +} + +/** + * Default values for the handling of response bodies. + */ +export const ResponseBodyConfigMapDefaults: ResponseBodyConfigMap = { + uint8array: ['application/octet-stream'], + json: ['application/json', 'text/json'], + text: ['text/plain', /test\/plain\+.*/, 'text/html', /test\/html\+.*/], + formData: ['application/x-www-form-urlencoded', 'multipart/form-data'], + blob: [/image\/.*/, /video\/.*/], + fallback: 'blob', +}; + +export interface MixFetchWebWorkerResponse { + body: ResponseBody; + url: string; + headers: any; + status: number; + statusText: string; + type: string; + ok: boolean; + redirected: boolean; +} diff --git a/sdk/typescript/packages/mix-fetch/src/worker/handle-response-mime-types.test.ts b/sdk/typescript/packages/mix-fetch/src/worker/handle-response-mime-types.test.ts new file mode 100644 index 0000000000..68c96e4999 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/src/worker/handle-response-mime-types.test.ts @@ -0,0 +1,45 @@ +import { handleResponseMimeTypes } from './handle-response-mime-types'; + +describe('handleResponseMimeTypes', () => { + test('gracefully handles empty values', async () => { + const resp = await handleResponseMimeTypes(new Response()); + expect(Object.values(resp)).toHaveLength(0); + }); + + test('handles text', async () => { + const TEXT = 'This is text'; + const resp = await handleResponseMimeTypes( + new Response(TEXT, { headers: new Headers([['Content-Type', 'text/plain']]) }), + ); + expect(resp.text).toBe(TEXT); + }); + test('handles images', async () => { + const DATA = new Uint8Array([0, 1, 2, 3]).buffer; + const resp = await handleResponseMimeTypes( + new Response(DATA, { headers: new Headers([['Content-Type', 'image/jpeg']]) }), + ); + expect(resp.blobUrl).toBeDefined(); + }); + test('handles videos', async () => { + const DATA = new Uint8Array([0, 1, 2, 3]).buffer; + const resp = await handleResponseMimeTypes( + new Response(DATA, { headers: new Headers([['Content-Type', 'video/mpeg4']]) }), + ); + expect(resp.blobUrl).toBeDefined(); + }); + test('handles form data when URL encoded', async () => { + const formData = 'foo=bar&baz=42'; + const resp = await handleResponseMimeTypes( + new Response(formData, { headers: new Headers([['Content-Type', 'application/x-www-form-urlencoded']]) }), + ); + expect(resp.formData.foo).toBe('bar'); + expect(resp.formData.baz).toBe('42'); + }); + test('handles JSON data', async () => { + const json = '{ "foo": "bar", "baz": 42 }'; + const resp = await handleResponseMimeTypes( + new Response(json, { headers: new Headers([['Content-Type', 'application/json']]) }), + ); + expect(resp.text).toBe(json); + }); +}); diff --git a/sdk/typescript/packages/mix-fetch/src/worker/handle-response-mime-types.ts b/sdk/typescript/packages/mix-fetch/src/worker/handle-response-mime-types.ts new file mode 100644 index 0000000000..abcaa845f7 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/src/worker/handle-response-mime-types.ts @@ -0,0 +1,111 @@ +import type { ResponseBody, ResponseBodyConfigMap, ResponseBodyMethod } from '../types'; +import { ResponseBodyConfigMapDefaults } from '../types'; + +const getContentType = (response?: Response) => { + if (!response) { + return undefined; + } + + // this is what should be returned in the headers + if (response.headers.has('Content-Type')) { + return response.headers.get('Content-Type') as string; + } + + // handle weird servers that use lowercase headers + if (response.headers.has('content-type')) { + return response.headers.get('content-type') as string; + } + + // the Content-Type/content-type header is not part of the response + return undefined; +}; + +const doHandleResponseMethod = async (response: Response, method?: ResponseBodyMethod): Promise => { + switch (method) { + case 'uint8array': + return { + uint8array: new Uint8Array(await response.arrayBuffer()), + }; + case 'json': + case 'text': + return { text: await response.text() }; + case 'blob': { + const blob = await response.blob(); + const blobUrl = URL.createObjectURL(blob); + return { blobUrl }; + } + case 'formData': { + const formData: any = {}; + const data = await response.formData(); + // eslint-disable-next-line no-restricted-syntax + for (const pair of data.entries()) { + const [key, value] = pair; + formData[key] = value; + } + return { formData }; + } + default: + return {}; + } +}; + +const testIfIncluded = (value?: string, tests?: Array): boolean => { + if (!tests) { + return false; + } + if (!value) { + return false; + } + + for (let i = 0; i < tests.length; i += 1) { + const test = tests[i]; + if (typeof test === 'string' && value === test) { + return true; + } + if ((test as RegExp).test && (test as RegExp).test(value)) { + return true; + } + } + + // default return is false, because nothing above matched + return false; +}; + +export const handleResponseMimeTypes = async ( + response: Response, + config?: ResponseBodyConfigMap, +): Promise => { + // combine the user supplied config with the default + const finalConfig: ResponseBodyConfigMap = { ...ResponseBodyConfigMapDefaults, ...config }; + + const contentType = getContentType(response); + + // check if the headers say what the content type are, otherwise return the bytes of the response as a blob + if (!contentType) { + // no content type, or body, so the response is only the status, e.g. GET + if (!response.body) { + return {}; + } + + // handle fallback method + return doHandleResponseMethod(response, config?.fallback || 'blob'); + } + + if (testIfIncluded(contentType, finalConfig.uint8array)) { + return doHandleResponseMethod(response, 'uint8array'); + } + if (testIfIncluded(contentType, finalConfig.json)) { + return doHandleResponseMethod(response, 'json'); + } + if (testIfIncluded(contentType, finalConfig.text)) { + return doHandleResponseMethod(response, 'text'); + } + if (testIfIncluded(contentType, finalConfig.formData)) { + return doHandleResponseMethod(response, 'formData'); + } + if (testIfIncluded(contentType, finalConfig.blob)) { + return doHandleResponseMethod(response, 'blob'); + } + + return {}; +}; diff --git a/sdk/typescript/packages/mix-fetch/src/worker/index.ts b/sdk/typescript/packages/mix-fetch/src/worker/index.ts new file mode 100644 index 0000000000..4fd508b348 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/src/worker/index.ts @@ -0,0 +1,9 @@ +import { loadWasm } from './wasm-loading'; +import { run } from './main'; + +async function main() { + await loadWasm(); + await run(); +} + +main().catch((e: any) => console.error('Unhandled exception in mixFetch worker', e)); diff --git a/sdk/typescript/packages/mix-fetch/src/worker/main.ts b/sdk/typescript/packages/mix-fetch/src/worker/main.ts new file mode 100644 index 0000000000..fee270b055 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/src/worker/main.ts @@ -0,0 +1,64 @@ +/* eslint-disable no-restricted-globals */ +import { setupMixFetch } from '@nymproject/mix-fetch-wasm'; +import * as Comlink from 'comlink'; +import type { IMixFetchWebWorker, LoadedEvent } from '../types'; +import { EventKinds, ResponseBodyConfigMap, ResponseBodyConfigMapDefaults } from '../types'; +import { handleResponseMimeTypes } from './handle-response-mime-types'; + +/** + * Helper method to send typed messages. + * @param event The strongly typed message to send back to the calling thread. + */ +// eslint-disable-next-line no-restricted-globals +const postMessageWithType = (event: E) => self.postMessage(event); +export async function run() { + const { mixFetch } = self as any; + let responseBodyConfigMap: ResponseBodyConfigMap = ResponseBodyConfigMapDefaults; + + const mixFetchWebWorker: IMixFetchWebWorker = { + mixFetch: async (url, args) => { + console.log('[Worker] --- mixFetch ---', { url, args }); + + const response: Response = await mixFetch(url, args); + + console.log('[Worker]', { response, json: JSON.stringify(response, null, 2) }); + + const bodyResponse = await handleResponseMimeTypes(response, responseBodyConfigMap); + console.log('[Worker]', { bodyResponse }); + + const headers: any = {}; + response.headers.forEach((value, key) => { + headers[key] = value; + }); + + const output = { + body: bodyResponse, + url: response.url, + headers, + status: response.status, + statusText: response.statusText, + type: response.type, + ok: response.ok, + redirected: response.redirected, + }; + + console.log('[Worker]', { output }); + + return output; + }, + setupMixFetch: async (opts) => { + console.log('[Worker] --- setupMixFetch ---', { opts }); + if (opts?.responseBodyConfigMap) { + responseBodyConfigMap = opts.responseBodyConfigMap; + } + await setupMixFetch(opts || {}); + }, + }; + + // start comlink listening for messages and handle them above + Comlink.expose(mixFetchWebWorker); + + // notify any listeners that the web worker has loaded - HOWEVER, mixFetch hasn't been setup and the client started + // call `setupMixFetch` from the main thread to start the Nym client + postMessageWithType({ kind: EventKinds.Loaded, args: { loaded: true } }); +} diff --git a/sdk/typescript/packages/mix-fetch/src/worker/wasm-loading.ts b/sdk/typescript/packages/mix-fetch/src/worker/wasm-loading.ts new file mode 100644 index 0000000000..1fa64b4c5d --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/src/worker/wasm-loading.ts @@ -0,0 +1,87 @@ +/* eslint-disable @typescript-eslint/naming-convention,no-restricted-globals */ +/// + +// Copyright 2020-2023 Nym Technologies SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +// Rollup will replace wasmBytes with a function that loads the WASM bundle from a base64 string embedded in the output. +// +// Doing it this way, saves having to support a large variety of bundlers and their quirks. +// +// @ts-ignore +// eslint-disable-next-line import/no-extraneous-dependencies +import getMixFetchWasmBytes from '@nymproject/mix-fetch-wasm/mix_fetch_wasm_bg.wasm'; + +// @ts-ignore +// eslint-disable-next-line import/no-extraneous-dependencies +import getGoConnectionWasmBytes from '@nymproject/mix-fetch-wasm/go_conn.wasm'; + +// wasm_bindgen creates a global variable (with the exports attached) that is in scope after `importScripts` +import init, { + set_panic_hook, + send_client_data, + start_new_mixnet_connection, + mix_fetch_initialised, + finish_mixnet_connection, +} from '@nymproject/mix-fetch-wasm'; + +// see `typings/wasm_exec.d.ts` for the defintion of the `class Go` in global scope +import '@nymproject/mix-fetch-wasm/wasm_exec'; + +async function loadGoWasm() { + // rollup will provide a function to get the Go connection WASM bytes here + const bytes = await getGoConnectionWasmBytes(); + + // @ts-ignore + const go = new Go(); // Defined in wasm_exec.js + + // the WebAssembly runtime will parse the bytes and then start the Go runtime + const wasmObj = await WebAssembly.instantiate(bytes, go.importObject); + go.run(wasmObj); +} + +function setupRsGoBridge() { + const rsGoBridge = { + send_client_data, + start_new_mixnet_connection, + mix_fetch_initialised, + finish_mixnet_connection, + }; + + // (note: reason for intermediate `__rs_go_bridge__` object is to decrease global scope bloat + // and to discourage users from trying to call those methods directly) + // eslint-disable-next-line no-underscore-dangle + (self as any).__rs_go_bridge__ = rsGoBridge; +} + +export async function loadWasm() { + // rollup with provide a function to get the mixFetch WASM bytes + const bytes = await getMixFetchWasmBytes(); + + // load rust WASM package + await init(bytes); + console.log('Loaded RUST WASM'); + + // load go WASM package + await loadGoWasm(); + console.log('Loaded GO WASM'); + + // sets up better stack traces in case of in-rust panics + set_panic_hook(); + + setupRsGoBridge(); + + // goWasmSetLogging('trace'); +} diff --git a/sdk/typescript/packages/mix-fetch/tsconfig.jest.json b/sdk/typescript/packages/mix-fetch/tsconfig.jest.json new file mode 100644 index 0000000000..2e6284589e --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/tsconfig.jest.json @@ -0,0 +1,43 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "lib": [ + "es2021", + "dom", + "dom.iterable", + "esnext", + "webworker" + ], + "module": "CommonJS", + "target": "es5", + "strict": true, + "moduleResolution": "node", + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "declaration": true, + "baseUrl": ".", + "esModuleInterop": true, + "allowJs": true, + "downlevelIteration": true + }, + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "jest.*", + "webpack.config.js", + "webpack.prod.js", + "webpack.common.js", + "node_modules", + "**/node_modules", + "dist", + "**/dist", + "scripts", + "jest", + "__tests__", + "**/__tests__", + "__jest__", + "**/__jest__", + "config/*" + ] +} diff --git a/sdk/typescript/packages/mix-fetch/tsconfig.json b/sdk/typescript/packages/mix-fetch/tsconfig.json new file mode 100644 index 0000000000..de7de44877 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/tsconfig.json @@ -0,0 +1,45 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "lib": [ + "es2021", + "dom", + "dom.iterable", + "esnext", + "webworker" + ], + "outDir": "./dist/", + "module": "esnext", + "target": "esnext", + "allowJs": false, + "strict": true, + "moduleResolution": "node", + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "declaration": true, + "baseUrl": ".", + "downlevelIteration": true + }, + "include": [ + "src/**/*.ts", + "src/*.ts", + "typings" + ], + "exclude": [ + "jest.config.js", + "webpack.config.js", + "webpack.prod.js", + "webpack.common.js", + "node_modules", + "**/node_modules", + "dist", + "**/dist", + "scripts", + "jest", + "__tests__", + "**/__tests__", + "__jest__", + "**/__jest__", + "config/*", + ] +} diff --git a/sdk/typescript/packages/mix-fetch/typedoc.json b/sdk/typescript/packages/mix-fetch/typedoc.json new file mode 100644 index 0000000000..46a91d8237 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/typedoc.json @@ -0,0 +1,32 @@ +{ + "sort": ["kind"], + "entryPoints": ["./src/index.ts"], + "out": "./docs", + "exclude": ["./src/worker/**"], + "kindSortOrder": [ + "Function", + "Interface", + "TypeAlias", + "Reference", + "Project", + "Module", + "Namespace", + "Enum", + "EnumMember", + "Class", + "Constructor", + "Property", + "Variable", + "Accessor", + "Method", + "ObjectLiteral", + "Parameter", + "TypeParameter", + "TypeLiteral", + "CallSignature", + "ConstructorSignature", + "IndexSignature", + "GetSignature", + "SetSignature" + ] +} diff --git a/sdk/typescript/packages/mix-fetch/typings/rollup-worker.d.ts b/sdk/typescript/packages/mix-fetch/typings/rollup-worker.d.ts new file mode 100644 index 0000000000..ead3d9e1f4 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/typings/rollup-worker.d.ts @@ -0,0 +1,4 @@ +declare module 'web-worker:*' { + const WorkerFactory: new () => Worker; + export default WorkerFactory; +} diff --git a/sdk/typescript/packages/mix-fetch/typings/wasm_exec.d.ts b/sdk/typescript/packages/mix-fetch/typings/wasm_exec.d.ts new file mode 100644 index 0000000000..9424fd386b --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/typings/wasm_exec.d.ts @@ -0,0 +1,11 @@ +declare module '@nymproject/mix-fetch-wasm/wasm_exec' { + export declare global { + class Go { + constructor(); + + importObject: any; + + run(goWasm: any); + } + } +} diff --git a/ts-packages/mui-theme/README.md b/sdk/typescript/packages/mui-theme/README.md similarity index 100% rename from ts-packages/mui-theme/README.md rename to sdk/typescript/packages/mui-theme/README.md diff --git a/ts-packages/mui-theme/package.json b/sdk/typescript/packages/mui-theme/package.json similarity index 97% rename from ts-packages/mui-theme/package.json rename to sdk/typescript/packages/mui-theme/package.json index c1f33a412e..1e74b7cb22 100644 --- a/ts-packages/mui-theme/package.json +++ b/sdk/typescript/packages/mui-theme/package.json @@ -37,6 +37,7 @@ "clean": "rimraf dist", "build": "tsc --noEmit false", "watch": "tsc --noEmit false -w", + "tsc": "tsc --noEmit true", "lint": "eslint src", "lint:fix": "eslint src --fix" } diff --git a/ts-packages/mui-theme/src/index.ts b/sdk/typescript/packages/mui-theme/src/index.ts similarity index 100% rename from ts-packages/mui-theme/src/index.ts rename to sdk/typescript/packages/mui-theme/src/index.ts diff --git a/ts-packages/mui-theme/src/theme/common.ts b/sdk/typescript/packages/mui-theme/src/theme/common.ts similarity index 100% rename from ts-packages/mui-theme/src/theme/common.ts rename to sdk/typescript/packages/mui-theme/src/theme/common.ts diff --git a/ts-packages/mui-theme/src/theme/index.tsx b/sdk/typescript/packages/mui-theme/src/theme/index.tsx similarity index 100% rename from ts-packages/mui-theme/src/theme/index.tsx rename to sdk/typescript/packages/mui-theme/src/theme/index.tsx diff --git a/ts-packages/mui-theme/src/theme/network-explorer.ts b/sdk/typescript/packages/mui-theme/src/theme/network-explorer.ts similarity index 100% rename from ts-packages/mui-theme/src/theme/network-explorer.ts rename to sdk/typescript/packages/mui-theme/src/theme/network-explorer.ts diff --git a/ts-packages/mui-theme/src/theme/theme.ts b/sdk/typescript/packages/mui-theme/src/theme/theme.ts similarity index 100% rename from ts-packages/mui-theme/src/theme/theme.ts rename to sdk/typescript/packages/mui-theme/src/theme/theme.ts diff --git a/ts-packages/mui-theme/src/theme/utils.ts b/sdk/typescript/packages/mui-theme/src/theme/utils.ts similarity index 100% rename from ts-packages/mui-theme/src/theme/utils.ts rename to sdk/typescript/packages/mui-theme/src/theme/utils.ts diff --git a/ts-packages/mui-theme/src/theme/wallet.ts b/sdk/typescript/packages/mui-theme/src/theme/wallet.ts similarity index 100% rename from ts-packages/mui-theme/src/theme/wallet.ts rename to sdk/typescript/packages/mui-theme/src/theme/wallet.ts diff --git a/ts-packages/react-webpack-with-theme-example/src/typings/FC.d.ts b/sdk/typescript/packages/mui-theme/src/typings/FC.d.ts similarity index 100% rename from ts-packages/react-webpack-with-theme-example/src/typings/FC.d.ts rename to sdk/typescript/packages/mui-theme/src/typings/FC.d.ts diff --git a/ts-packages/mui-theme/template/mui-theme.d.ts b/sdk/typescript/packages/mui-theme/template/mui-theme.d.ts similarity index 100% rename from ts-packages/mui-theme/template/mui-theme.d.ts rename to sdk/typescript/packages/mui-theme/template/mui-theme.d.ts diff --git a/ts-packages/mui-theme/tsconfig.json b/sdk/typescript/packages/mui-theme/tsconfig.json similarity index 86% rename from ts-packages/mui-theme/tsconfig.json rename to sdk/typescript/packages/mui-theme/tsconfig.json index adabac7c0e..2ce06c54b9 100644 --- a/ts-packages/mui-theme/tsconfig.json +++ b/sdk/typescript/packages/mui-theme/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../tsconfig.json", + "extends": "../../tsconfig.json", "compilerOptions": { "baseUrl": "./", "outDir": "./dist", diff --git a/sdk/typescript/packages/node-tester/.babelrc b/sdk/typescript/packages/node-tester/.babelrc new file mode 100644 index 0000000000..0ef5ffc214 --- /dev/null +++ b/sdk/typescript/packages/node-tester/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@babel/env"] +} diff --git a/sdk/typescript/packages/node-tester/.gitignore b/sdk/typescript/packages/node-tester/.gitignore new file mode 100644 index 0000000000..d0b3e5e3ff --- /dev/null +++ b/sdk/typescript/packages/node-tester/.gitignore @@ -0,0 +1 @@ +src/worker.js diff --git a/sdk/typescript/packages/node-tester/README-CommonJS-full-fat.md b/sdk/typescript/packages/node-tester/README-CommonJS-full-fat.md new file mode 100644 index 0000000000..cc17ad4fb3 --- /dev/null +++ b/sdk/typescript/packages/node-tester/README-CommonJS-full-fat.md @@ -0,0 +1,7 @@ +# Nym Node Tester + +This package provides a WASM library to test if a Nym node can process packets. + +## Usage + +TODO diff --git a/sdk/typescript/packages/node-tester/README-CommonJS.md b/sdk/typescript/packages/node-tester/README-CommonJS.md new file mode 100644 index 0000000000..cc17ad4fb3 --- /dev/null +++ b/sdk/typescript/packages/node-tester/README-CommonJS.md @@ -0,0 +1,7 @@ +# Nym Node Tester + +This package provides a WASM library to test if a Nym node can process packets. + +## Usage + +TODO diff --git a/sdk/typescript/packages/node-tester/README-full-fat.md b/sdk/typescript/packages/node-tester/README-full-fat.md new file mode 100644 index 0000000000..cc17ad4fb3 --- /dev/null +++ b/sdk/typescript/packages/node-tester/README-full-fat.md @@ -0,0 +1,7 @@ +# Nym Node Tester + +This package provides a WASM library to test if a Nym node can process packets. + +## Usage + +TODO diff --git a/sdk/typescript/packages/node-tester/README.md b/sdk/typescript/packages/node-tester/README.md new file mode 100644 index 0000000000..cc17ad4fb3 --- /dev/null +++ b/sdk/typescript/packages/node-tester/README.md @@ -0,0 +1,7 @@ +# Nym Node Tester + +This package provides a WASM library to test if a Nym node can process packets. + +## Usage + +TODO diff --git a/sdk/typescript/packages/node-tester/jest.config.mjs b/sdk/typescript/packages/node-tester/jest.config.mjs new file mode 100644 index 0000000000..ed5b112c72 --- /dev/null +++ b/sdk/typescript/packages/node-tester/jest.config.mjs @@ -0,0 +1,15 @@ +import preset from 'ts-jest/presets/index.js' + +/** @type {import('ts-jest').JestConfigWithTsJest} */ +export default { + ...preset.defaults, + transform: { + '^.+\\.(ts|tsx)$': [ + 'ts-jest', + { + tsconfig: 'tsconfig.jest.json', + useESM: true, + }, + ], + }, +} diff --git a/sdk/typescript/packages/node-tester/package.json b/sdk/typescript/packages/node-tester/package.json new file mode 100644 index 0000000000..33ab25cbbf --- /dev/null +++ b/sdk/typescript/packages/node-tester/package.json @@ -0,0 +1,74 @@ +{ + "name": "@nymproject/node-tester", + "version": "1.2.0-rc.2", + "description": "This package provides a tester that can send test packets to mixnode that is part of the Nym Mixnet.", + "license": "Apache-2.0", + "author": "Nym Technologies SA", + "files": [ + "dist/esm/worker.js", + "dist/cjs/worker.js", + "dist/**/*" + ], + "main": "dist/cjs/index.js", + "browser": "dist/esm/index.js", + "scripts": { + "build": "scripts/build-prod.sh", + "build:dev": "scripts/build.sh", + "build:dev:esm": "scripts/build-dev-esm.sh", + "build:worker": "rollup -c rollup-worker.config.mjs", + "clean": "rimraf dist", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "tsc -w", + "start:dev": "nodemon --watch src -e ts,json --exec 'yarn build:dev:esm'", + "test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache", + "tsc": "tsc --noEmit true" + }, + "dependencies": { + "@nymproject/nym-node-tester-wasm": ">=1.2.0-rc.0 || ^1", + "comlink": "^4.3.1" + }, + "devDependencies": { + "@babel/core": "^7.15.0", + "@babel/plugin-transform-async-to-generator": "^7.14.5", + "@babel/preset-env": "^7.15.0", + "@babel/preset-react": "^7.14.5", + "@babel/preset-typescript": "^7.15.0", + "@nymproject/eslint-config-react-typescript": "^1.0.0", + "@rollup/plugin-commonjs": "^24.0.1", + "@rollup/plugin-inject": "^5.0.3", + "@rollup/plugin-json": "^6.0.0", + "@rollup/plugin-node-resolve": "^15.0.1", + "@rollup/plugin-replace": "^5.0.2", + "@rollup/plugin-terser": "^0.2.1", + "@rollup/plugin-typescript": "^10.0.1", + "@rollup/plugin-wasm": "^6.1.1", + "@types/jest": "^27.0.1", + "@types/node": "^16.7.13", + "@typescript-eslint/eslint-plugin": "^5.13.0", + "@typescript-eslint/parser": "^5.13.0", + "eslint": "^8.10.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-airbnb-typescript": "^16.1.0", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-root-import": "^1.0.4", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^26.1.1", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-react": "^7.29.2", + "eslint-plugin-react-hooks": "^4.3.0", + "jest": "^29.5.0", + "nodemon": "^2.0.21", + "rimraf": "^3.0.2", + "rollup": "^3.9.1", + "rollup-plugin-base64": "^1.0.1", + "rollup-plugin-web-worker-loader": "^1.6.1", + "ts-jest": "^29.1.0", + "ts-loader": "^9.4.2", + "typescript": "^4.8.4" + }, + "private": false, + "type": "module", + "types": "./dist/esm/index.d.ts" +} \ No newline at end of file diff --git a/sdk/typescript/packages/node-tester/rollup-cjs-full-fat.config.mjs b/sdk/typescript/packages/node-tester/rollup-cjs-full-fat.config.mjs new file mode 100644 index 0000000000..d4c6e39e99 --- /dev/null +++ b/sdk/typescript/packages/node-tester/rollup-cjs-full-fat.config.mjs @@ -0,0 +1,8 @@ +import { getConfig } from './rollup/cjs.mjs'; + +export default { + ...getConfig({ + inline: true, + outputDir: 'dist/cjs-full-fat', + }), +}; diff --git a/sdk/typescript/packages/node-tester/rollup-cjs.config.mjs b/sdk/typescript/packages/node-tester/rollup-cjs.config.mjs new file mode 100644 index 0000000000..a12e5bdb7a --- /dev/null +++ b/sdk/typescript/packages/node-tester/rollup-cjs.config.mjs @@ -0,0 +1,5 @@ +import { getConfig } from './rollup/cjs.mjs'; + +export default { + ...getConfig({ inline: false }), +}; diff --git a/sdk/typescript/packages/node-tester/rollup-esm-full-fat.config.mjs b/sdk/typescript/packages/node-tester/rollup-esm-full-fat.config.mjs new file mode 100644 index 0000000000..ea80b1997b --- /dev/null +++ b/sdk/typescript/packages/node-tester/rollup-esm-full-fat.config.mjs @@ -0,0 +1,8 @@ +import { getConfig } from './rollup/esm.mjs'; + +export default { + ...getConfig({ + inline: true, + outputDir: 'dist/esm-full-fat', + }), +}; diff --git a/sdk/typescript/packages/node-tester/rollup-esm.config.mjs b/sdk/typescript/packages/node-tester/rollup-esm.config.mjs new file mode 100644 index 0000000000..fe7b0082bb --- /dev/null +++ b/sdk/typescript/packages/node-tester/rollup-esm.config.mjs @@ -0,0 +1,8 @@ +import { getConfig } from './rollup/esm.mjs'; + +export default { + ...getConfig({ + // by default, the web worker will not be inlined, in local development mode it will be + inline: process.env.MIX_FETCH_DEV_MODE === 'true', + }), +}; diff --git a/sdk/typescript/packages/sdk/rollup-node-tester-worker.config.mjs b/sdk/typescript/packages/node-tester/rollup-worker.config.mjs similarity index 79% rename from sdk/typescript/packages/sdk/rollup-node-tester-worker.config.mjs rename to sdk/typescript/packages/node-tester/rollup-worker.config.mjs index 5f18e7ce33..b34376618c 100644 --- a/sdk/typescript/packages/sdk/rollup-node-tester-worker.config.mjs +++ b/sdk/typescript/packages/node-tester/rollup-worker.config.mjs @@ -3,10 +3,12 @@ import resolve from '@rollup/plugin-node-resolve'; import { wasm } from '@rollup/plugin-wasm'; import replace from '@rollup/plugin-replace'; -const extensions = ['.js', '.jsx', '.ts', '.tsx']; +const extensions = [ + '.js', '.jsx', '.ts', '.tsx', +]; export default { - input: 'src/mixnet/node-tester/worker.ts', + input: 'src/worker.ts', output: { dir: 'dist', format: 'cjs', @@ -15,7 +17,7 @@ export default { resolve({ extensions }), // this is some nasty monkey patching that removes the WASM URL (because it is handled by the `wasm` plugin) replace({ - values: { "input = new URL('nym_client_wasm_bg.wasm', import.meta.url);": 'input = undefined;' }, + values: { 'input = new URL(\'mix_fetch_wasm_bg.wasm\', import.meta.url);': 'input = undefined;' }, delimiters: ['', ''], preventAssignment: true, }), diff --git a/sdk/typescript/packages/node-tester/rollup/cjs.mjs b/sdk/typescript/packages/node-tester/rollup/cjs.mjs new file mode 100644 index 0000000000..18c6f5e8c0 --- /dev/null +++ b/sdk/typescript/packages/node-tester/rollup/cjs.mjs @@ -0,0 +1,30 @@ +import typescript from '@rollup/plugin-typescript'; +import resolve from '@rollup/plugin-node-resolve'; +import { wasm } from '@rollup/plugin-wasm'; +import webWorkerLoader from 'rollup-plugin-web-worker-loader'; + +const extensions = ['.js', '.jsx', '.ts', '.tsx']; + +/** + * Gets the config for bundling the package as a CommonJS module. + * + * @param opts Options: + * `{ inline: boolean }` - set inline to true to inline the web worker in the main bundle + * `{ outputDir: string }` - override the destination + */ +export const getConfig = (opts) => ({ + input: 'src/index.ts', + output: { + dir: opts.outputDir || 'dist/cjs', + format: 'cjs', + }, + plugins: [ + webWorkerLoader({ targetPlatform: 'browser', inline: opts.inline }), // the inline param is used here + resolve({ extensions }), + wasm({ maxFileSize: 10000000, targetEnv: 'browser' }), + typescript({ + compilerOptions: { outDir: opts.outputDir || 'dist/cjs', target: 'es5' }, + exclude: ['worker.ts'], + }), + ], +}); diff --git a/sdk/typescript/packages/node-tester/rollup/esm.mjs b/sdk/typescript/packages/node-tester/rollup/esm.mjs new file mode 100644 index 0000000000..b47cf1ac05 --- /dev/null +++ b/sdk/typescript/packages/node-tester/rollup/esm.mjs @@ -0,0 +1,28 @@ +import typescript from '@rollup/plugin-typescript'; +import resolve from '@rollup/plugin-node-resolve'; +import webWorkerLoader from 'rollup-plugin-web-worker-loader'; + +const extensions = ['.js', '.jsx', '.ts', '.tsx']; + +/** + * Gets the config for bundling the package as an ES Module. + * + * @param opts Options: + * `{ inline: boolean }` - set inline to true to inline the web worker in the main bundle + * `{ outputDir: string }` - override the destination * + */ +export const getConfig = (opts) => ({ + input: 'src/index.ts', + output: { + dir: opts.outputDir || 'dist/esm', + format: 'es', + }, + plugins: [ + webWorkerLoader({ targetPlatform: 'browser', inline: opts.inline }), // the inline param is used here + resolve({ extensions }), + typescript({ + exclude: ['worker.ts'], + compilerOptions: { outDir: opts.outputDir || 'dist/esm' }, + }), + ], +}); diff --git a/sdk/typescript/packages/node-tester/scripts/build-dev-esm.sh b/sdk/typescript/packages/node-tester/scripts/build-dev-esm.sh new file mode 100755 index 0000000000..26970fc4e6 --- /dev/null +++ b/sdk/typescript/packages/node-tester/scripts/build-dev-esm.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +#------------------------------------------------------- +# WEB WORKER (node-tester WASM) +#------------------------------------------------------- +# The web worker needs to be bundled because the WASM bundle needs to be loaded synchronously and all dependencies +# must be included in the worker script (because it is not loaded as an ES Module) + +# build the worker +rollup -c rollup-worker.config.mjs + +# move it next to the Typescript `src/index.ts` so it can be inlined by rollup +cp dist/worker.js src/worker.js +rm dist/worker.js + +#------------------------------------------------------- +# ESM +#------------------------------------------------------- + +# build the SDK as a ESM bundle +rollup -c rollup-esm.config.mjs + +#------------------------------------------------------- +# CLEAN UP +#------------------------------------------------------- + +rm -rf dist/esm/worker + + diff --git a/sdk/typescript/packages/node-tester/scripts/build-prod.sh b/sdk/typescript/packages/node-tester/scripts/build-prod.sh new file mode 100755 index 0000000000..74a173acc8 --- /dev/null +++ b/sdk/typescript/packages/node-tester/scripts/build-prod.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf dist || true +rm -rf ../../../../dist/ts/sdk/node-tester || true + +# run the build +scripts/build.sh +node scripts/buildPackageJson.mjs + +# move the output outside of the yarn/npm workspaces +mkdir -p ../../../../dist/ts/sdk +mv dist ../../../../dist/ts/sdk +mv ../../../../dist/ts/sdk/dist ../../../../dist/ts/sdk/node-tester + +echo "Output can be found in:" +realpath ../../../../dist/ts/sdk/node-tester diff --git a/sdk/typescript/packages/node-tester/scripts/build.sh b/sdk/typescript/packages/node-tester/scripts/build.sh new file mode 100755 index 0000000000..64ed2e4381 --- /dev/null +++ b/sdk/typescript/packages/node-tester/scripts/build.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf dist || true + +#------------------------------------------------------- +# WEB WORKER (mix-fetch WASM) +#------------------------------------------------------- +# The web worker needs to be bundled because the WASM bundle needs to be loaded synchronously and all dependencies +# must be included in the worker script (because it is not loaded as an ES Module) + +# build the worker +rollup -c rollup-worker.config.mjs + +# move it next to the Typescript `src/index.ts` so it can be inlined by rollup +rm -f src/worker.js +mv dist/worker.js src/worker.js + +#------------------------------------------------------- +# ESM +#------------------------------------------------------- + +# build the SDK as a ESM bundle +rollup -c rollup-esm.config.mjs + +#------------------------------------------------------- +# COMMON JS +#------------------------------------------------------- +# Some old build systems cannot fully handle ESM or ES2021, so build +# a CommonJS bundle targeting ES5 + +# build the SDK as a CommonJS bundle +rollup -c rollup-cjs.config.mjs + +#------------------------------------------------------- +# ESM (full-fat) +#------------------------------------------------------- + +# build the SDK as a ESM bundle (with worker inlined as a blob) +rollup -c rollup-esm-full-fat.config.mjs + +#------------------------------------------------------- +# COMMON JS (full-fat) +#------------------------------------------------------- +# Some old build systems cannot fully handle ESM or ES2021, so build +# a CommonJS bundle targeting ES5 + +# build the SDK as a CommonJS bundle (with worker inlined as a blob) +rollup -c rollup-cjs-full-fat.config.mjs + +#------------------------------------------------------- +# CLEAN UP +#------------------------------------------------------- + +rm -rf dist/cjs/worker +rm -rf dist/esm/worker +rm -rf dist/cjs-full-fat/worker +rm -rf dist/esm-full-fat/worker + +# copy README +cp README.md dist/esm +cp README-CommonJS.md dist/cjs/README.md +cp README-CommonJS-full-fat.md dist/cjs-full-fat/README.md +cp README-full-fat.md dist/esm-full-fat/README.md + + diff --git a/sdk/typescript/packages/node-tester/scripts/buildPackageJson.mjs b/sdk/typescript/packages/node-tester/scripts/buildPackageJson.mjs new file mode 100644 index 0000000000..3fc5a7b5b2 --- /dev/null +++ b/sdk/typescript/packages/node-tester/scripts/buildPackageJson.mjs @@ -0,0 +1,29 @@ +import * as fs from 'fs'; + +// parse the package.json from the SDK, so we can keep fields like the name and version +const json = JSON.parse(fs.readFileSync('package.json').toString()); + +// defaults (NB: these are in the output file locations) +const browser = 'index.js'; +const main = 'index.js'; +const types = 'index.d.ts'; + +const getPackageJson = (type, suffix) => ({ + name: `${json.name}${suffix ? `-${suffix}` : ''}`, + version: json.version, + license: json.license, + author: json.author, + type, + browser, + main, + types, +}); + +fs.writeFileSync('dist/cjs/package.json', JSON.stringify(getPackageJson('commonjs', 'commonjs'), null, 2)); +fs.writeFileSync('dist/esm/package.json', JSON.stringify(getPackageJson('module'), null, 2)); + +fs.writeFileSync( + 'dist/cjs-full-fat/package.json', + JSON.stringify(getPackageJson('commonjs', 'commonjs-full-fat'), null, 2), +); +fs.writeFileSync('dist/esm-full-fat/package.json', JSON.stringify(getPackageJson('module', 'full-fat'), null, 2)); diff --git a/sdk/typescript/packages/node-tester/scripts/publish.sh b/sdk/typescript/packages/node-tester/scripts/publish.sh new file mode 100755 index 0000000000..f08bcf3068 --- /dev/null +++ b/sdk/typescript/packages/node-tester/scripts/publish.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +yarn +yarn build +cd ../../../../dist/ts/sdk/node-tester + +cd cjs +echo "Publishing CommonJS package to NPM.." +npm publish --access=public +cd .. + +cd esm +echo "Publishing ESM package to NPM.." +npm publish --access=public +cd .. diff --git a/sdk/typescript/packages/sdk/src/mixnet/node-tester/index.ts b/sdk/typescript/packages/node-tester/src/index.ts similarity index 98% rename from sdk/typescript/packages/sdk/src/mixnet/node-tester/index.ts rename to sdk/typescript/packages/node-tester/src/index.ts index 04e52ee579..230ed9490a 100644 --- a/sdk/typescript/packages/sdk/src/mixnet/node-tester/index.ts +++ b/sdk/typescript/packages/node-tester/src/index.ts @@ -48,3 +48,5 @@ const createWorker = async () => { once: true }, ); }); + +export * from './types'; diff --git a/sdk/typescript/packages/sdk/src/mixnet/node-tester/types.ts b/sdk/typescript/packages/node-tester/src/types.ts similarity index 100% rename from sdk/typescript/packages/sdk/src/mixnet/node-tester/types.ts rename to sdk/typescript/packages/node-tester/src/types.ts diff --git a/sdk/typescript/packages/sdk/src/mixnet/node-tester/worker.ts b/sdk/typescript/packages/node-tester/src/worker.ts similarity index 91% rename from sdk/typescript/packages/sdk/src/mixnet/node-tester/worker.ts rename to sdk/typescript/packages/node-tester/src/worker.ts index ec51afd3ce..2251ac3909 100644 --- a/sdk/typescript/packages/sdk/src/mixnet/node-tester/worker.ts +++ b/sdk/typescript/packages/node-tester/src/worker.ts @@ -21,10 +21,10 @@ import * as Comlink from 'comlink'; // // @ts-ignore // eslint-disable-next-line import/no-extraneous-dependencies -import wasmBytes from '@nymproject/nym-client-wasm/nym_client_wasm_bg.wasm'; +import wasmBytes from '@nymproject/nym-node-tester-wasm/nym_node_tester_wasm_bg.wasm'; /* eslint-disable no-restricted-globals */ -import init, { NymNodeTester, current_network_topology, NodeTestResult } from '@nymproject/nym-client-wasm'; +import init, { NymNodeTester, NodeTestResult } from '@nymproject/nym-node-tester-wasm/nym_node_tester_wasm'; import type { INodeTesterWorkerAsync, NodeTesterLoadedEvent } from './types'; import { NodeTesterEventKinds } from './types'; @@ -37,10 +37,8 @@ const postMessageWithType = (event: E) => self.postMessage(event); console.log('[Nym WASM client] Starting Nym WASM web worker...'); -const buildTester = async (validatorUrl: string, nodeTesterId?: string): Promise => { - const topology = await current_network_topology(validatorUrl); - return new NymNodeTester(topology, nodeTesterId); -}; +const buildTester = async (validatorUrl: string, nodeTesterId?: string): Promise => + new NymNodeTester({ nymApi: validatorUrl, id: nodeTesterId }); async function main() { const importResult = await init(wasmBytes()); diff --git a/sdk/typescript/packages/node-tester/tsconfig.jest.json b/sdk/typescript/packages/node-tester/tsconfig.jest.json new file mode 100644 index 0000000000..2e6284589e --- /dev/null +++ b/sdk/typescript/packages/node-tester/tsconfig.jest.json @@ -0,0 +1,43 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "lib": [ + "es2021", + "dom", + "dom.iterable", + "esnext", + "webworker" + ], + "module": "CommonJS", + "target": "es5", + "strict": true, + "moduleResolution": "node", + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "declaration": true, + "baseUrl": ".", + "esModuleInterop": true, + "allowJs": true, + "downlevelIteration": true + }, + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "jest.*", + "webpack.config.js", + "webpack.prod.js", + "webpack.common.js", + "node_modules", + "**/node_modules", + "dist", + "**/dist", + "scripts", + "jest", + "__tests__", + "**/__tests__", + "__jest__", + "**/__jest__", + "config/*" + ] +} diff --git a/sdk/typescript/packages/node-tester/tsconfig.json b/sdk/typescript/packages/node-tester/tsconfig.json new file mode 100644 index 0000000000..de7de44877 --- /dev/null +++ b/sdk/typescript/packages/node-tester/tsconfig.json @@ -0,0 +1,45 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "lib": [ + "es2021", + "dom", + "dom.iterable", + "esnext", + "webworker" + ], + "outDir": "./dist/", + "module": "esnext", + "target": "esnext", + "allowJs": false, + "strict": true, + "moduleResolution": "node", + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "declaration": true, + "baseUrl": ".", + "downlevelIteration": true + }, + "include": [ + "src/**/*.ts", + "src/*.ts", + "typings" + ], + "exclude": [ + "jest.config.js", + "webpack.config.js", + "webpack.prod.js", + "webpack.common.js", + "node_modules", + "**/node_modules", + "dist", + "**/dist", + "scripts", + "jest", + "__tests__", + "**/__tests__", + "__jest__", + "**/__jest__", + "config/*", + ] +} diff --git a/sdk/typescript/packages/node-tester/typings/rollup-worker.d.ts b/sdk/typescript/packages/node-tester/typings/rollup-worker.d.ts new file mode 100644 index 0000000000..ead3d9e1f4 --- /dev/null +++ b/sdk/typescript/packages/node-tester/typings/rollup-worker.d.ts @@ -0,0 +1,4 @@ +declare module 'web-worker:*' { + const WorkerFactory: new () => Worker; + export default WorkerFactory; +} diff --git a/sdk/typescript/packages/nym-client-wasm/BUILD.md b/sdk/typescript/packages/nym-client-wasm/BUILD.md deleted file mode 100644 index f3d393c9b8..0000000000 --- a/sdk/typescript/packages/nym-client-wasm/BUILD.md +++ /dev/null @@ -1,39 +0,0 @@ -# `@nym-project/nym-client-wasm` - -This package contains a WASM client for using the Nym mixnet. - -## Usage - -You should use `@nym-project/sdk` instead of using this package directory. - -If you want to use it directly, you'll need to configure bundling and interop as suits your project. - -## Build - -The build process is a bit nasty. This is necessary to make the package easier to consume. - -Build the package by running the following from this directory: - -``` -scripts/build.sh -``` - -The following files will be copied into this directory, so that it becomes a package that can be used by the `@nym-project/sdk` package: - -``` -nym_client_wasm.d.ts -nym_client_wasm.js -nym_client_wasm_bg.wasm -nym_client_wasm_bg.wasm.d.ts -package.json -``` - -## Publish to `npm` - -First build the package with the instructions above. - -Publish to `npm` with: - -``` -npm publish -``` \ No newline at end of file diff --git a/sdk/typescript/packages/nym-client-wasm/scripts/build.sh b/sdk/typescript/packages/nym-client-wasm/scripts/build.sh deleted file mode 100755 index 5db2aea640..0000000000 --- a/sdk/typescript/packages/nym-client-wasm/scripts/build.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -# change to the same directory as the script, then go up one -cd "$(dirname "$0")" -cd .. - -# clear out any files and suppress missing file errors -rm -f nym_client_wasm* package.json || true - -# let wasm-pack build the files and put them in the output location rather than `./pkg` -cd ../../../../clients/webassembly -wasm-pack build --scope nymproject --target web --out-dir ../../sdk/typescript/packages/nym-client-wasm - -# run wasm-opt manually to circumvent wasm-pack issues with Apple Silicon -cd ../../sdk/typescript/packages/nym-client-wasm -wasm-opt -O4 nym_client_wasm_bg.wasm -o nym_client_wasm_bg.wasm - -# clean up some files that come with the build -rm README.md LICENSE_APACHE diff --git a/sdk/typescript/packages/react-components/.eslintrc.json b/sdk/typescript/packages/react-components/.eslintrc.json new file mode 100644 index 0000000000..83e95d88a7 --- /dev/null +++ b/sdk/typescript/packages/react-components/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "parserOptions": { + "project": "./tsconfig.eslint.json" + } +} diff --git a/ts-packages/react-components/.storybook/main.js b/sdk/typescript/packages/react-components/.storybook/main.js similarity index 100% rename from ts-packages/react-components/.storybook/main.js rename to sdk/typescript/packages/react-components/.storybook/main.js diff --git a/ts-packages/react-components/.storybook/preview.js b/sdk/typescript/packages/react-components/.storybook/preview.js similarity index 100% rename from ts-packages/react-components/.storybook/preview.js rename to sdk/typescript/packages/react-components/.storybook/preview.js diff --git a/ts-packages/react-components/README.md b/sdk/typescript/packages/react-components/README.md similarity index 100% rename from ts-packages/react-components/README.md rename to sdk/typescript/packages/react-components/README.md diff --git a/ts-packages/react-components/package.json b/sdk/typescript/packages/react-components/package.json similarity index 98% rename from ts-packages/react-components/package.json rename to sdk/typescript/packages/react-components/package.json index 47fd5dd87c..6322ded2af 100644 --- a/ts-packages/react-components/package.json +++ b/sdk/typescript/packages/react-components/package.json @@ -82,6 +82,7 @@ }, "scripts": { "clean": "rimraf dist", + "tsc": "tsc --noEmit true", "build": "tsc --noEmit false", "watch": "tsc --noEmit false -w", "lint": "eslint src .storybook", diff --git a/ts-packages/react-components/src/components/account/WalletAddressFormField.stories.tsx b/sdk/typescript/packages/react-components/src/components/account/WalletAddressFormField.stories.tsx similarity index 100% rename from ts-packages/react-components/src/components/account/WalletAddressFormField.stories.tsx rename to sdk/typescript/packages/react-components/src/components/account/WalletAddressFormField.stories.tsx diff --git a/ts-packages/react-components/src/components/account/WalletAddressFormField.tsx b/sdk/typescript/packages/react-components/src/components/account/WalletAddressFormField.tsx similarity index 100% rename from ts-packages/react-components/src/components/account/WalletAddressFormField.tsx rename to sdk/typescript/packages/react-components/src/components/account/WalletAddressFormField.tsx diff --git a/ts-packages/react-components/src/components/banners/MaintenanceBanner.tsx b/sdk/typescript/packages/react-components/src/components/banners/MaintenanceBanner.tsx similarity index 100% rename from ts-packages/react-components/src/components/banners/MaintenanceBanner.tsx rename to sdk/typescript/packages/react-components/src/components/banners/MaintenanceBanner.tsx diff --git a/ts-packages/react-components/src/components/client-address/ClientAddress.stories.tsx b/sdk/typescript/packages/react-components/src/components/client-address/ClientAddress.stories.tsx similarity index 100% rename from ts-packages/react-components/src/components/client-address/ClientAddress.stories.tsx rename to sdk/typescript/packages/react-components/src/components/client-address/ClientAddress.stories.tsx diff --git a/ts-packages/react-components/src/components/client-address/ClientAddress.tsx b/sdk/typescript/packages/react-components/src/components/client-address/ClientAddress.tsx similarity index 100% rename from ts-packages/react-components/src/components/client-address/ClientAddress.tsx rename to sdk/typescript/packages/react-components/src/components/client-address/ClientAddress.tsx diff --git a/ts-packages/react-components/src/components/clipboard/CopyToClipboard.stories.tsx b/sdk/typescript/packages/react-components/src/components/clipboard/CopyToClipboard.stories.tsx similarity index 100% rename from ts-packages/react-components/src/components/clipboard/CopyToClipboard.stories.tsx rename to sdk/typescript/packages/react-components/src/components/clipboard/CopyToClipboard.stories.tsx diff --git a/ts-packages/react-components/src/components/clipboard/CopyToClipboard.tsx b/sdk/typescript/packages/react-components/src/components/clipboard/CopyToClipboard.tsx similarity index 100% rename from ts-packages/react-components/src/components/clipboard/CopyToClipboard.tsx rename to sdk/typescript/packages/react-components/src/components/clipboard/CopyToClipboard.tsx diff --git a/ts-packages/react-components/src/components/coins/CoinMark.stories.tsx b/sdk/typescript/packages/react-components/src/components/coins/CoinMark.stories.tsx similarity index 100% rename from ts-packages/react-components/src/components/coins/CoinMark.stories.tsx rename to sdk/typescript/packages/react-components/src/components/coins/CoinMark.stories.tsx diff --git a/ts-packages/react-components/src/components/coins/CoinMark.tsx b/sdk/typescript/packages/react-components/src/components/coins/CoinMark.tsx similarity index 100% rename from ts-packages/react-components/src/components/coins/CoinMark.tsx rename to sdk/typescript/packages/react-components/src/components/coins/CoinMark.tsx diff --git a/ts-packages/react-components/src/components/coins/CoinMarkTestnet.stories.tsx b/sdk/typescript/packages/react-components/src/components/coins/CoinMarkTestnet.stories.tsx similarity index 100% rename from ts-packages/react-components/src/components/coins/CoinMarkTestnet.stories.tsx rename to sdk/typescript/packages/react-components/src/components/coins/CoinMarkTestnet.stories.tsx diff --git a/ts-packages/react-components/src/components/coins/CoinMarkTestnet.tsx b/sdk/typescript/packages/react-components/src/components/coins/CoinMarkTestnet.tsx similarity index 100% rename from ts-packages/react-components/src/components/coins/CoinMarkTestnet.tsx rename to sdk/typescript/packages/react-components/src/components/coins/CoinMarkTestnet.tsx diff --git a/ts-packages/react-components/src/components/currency/Currency.stories.tsx b/sdk/typescript/packages/react-components/src/components/currency/Currency.stories.tsx similarity index 100% rename from ts-packages/react-components/src/components/currency/Currency.stories.tsx rename to sdk/typescript/packages/react-components/src/components/currency/Currency.stories.tsx diff --git a/ts-packages/react-components/src/components/currency/Currency.tsx b/sdk/typescript/packages/react-components/src/components/currency/Currency.tsx similarity index 100% rename from ts-packages/react-components/src/components/currency/Currency.tsx rename to sdk/typescript/packages/react-components/src/components/currency/Currency.tsx diff --git a/ts-packages/react-components/src/components/currency/CurrencyAmount.stories.tsx b/sdk/typescript/packages/react-components/src/components/currency/CurrencyAmount.stories.tsx similarity index 100% rename from ts-packages/react-components/src/components/currency/CurrencyAmount.stories.tsx rename to sdk/typescript/packages/react-components/src/components/currency/CurrencyAmount.stories.tsx diff --git a/ts-packages/react-components/src/components/currency/CurrencyAmount.tsx b/sdk/typescript/packages/react-components/src/components/currency/CurrencyAmount.tsx similarity index 100% rename from ts-packages/react-components/src/components/currency/CurrencyAmount.tsx rename to sdk/typescript/packages/react-components/src/components/currency/CurrencyAmount.tsx diff --git a/ts-packages/react-components/src/components/currency/CurrencyFormField.stories.tsx b/sdk/typescript/packages/react-components/src/components/currency/CurrencyFormField.stories.tsx similarity index 100% rename from ts-packages/react-components/src/components/currency/CurrencyFormField.stories.tsx rename to sdk/typescript/packages/react-components/src/components/currency/CurrencyFormField.stories.tsx diff --git a/ts-packages/react-components/src/components/currency/CurrencyFormField.tsx b/sdk/typescript/packages/react-components/src/components/currency/CurrencyFormField.tsx similarity index 100% rename from ts-packages/react-components/src/components/currency/CurrencyFormField.tsx rename to sdk/typescript/packages/react-components/src/components/currency/CurrencyFormField.tsx diff --git a/ts-packages/react-components/src/components/currency/CurrencyWithCoinMark.tsx b/sdk/typescript/packages/react-components/src/components/currency/CurrencyWithCoinMark.tsx similarity index 100% rename from ts-packages/react-components/src/components/currency/CurrencyWithCoinMark.tsx rename to sdk/typescript/packages/react-components/src/components/currency/CurrencyWithCoinMark.tsx diff --git a/ts-packages/react-components/src/components/link/Link.stories.tsx b/sdk/typescript/packages/react-components/src/components/link/Link.stories.tsx similarity index 100% rename from ts-packages/react-components/src/components/link/Link.stories.tsx rename to sdk/typescript/packages/react-components/src/components/link/Link.stories.tsx diff --git a/ts-packages/react-components/src/components/link/Link.tsx b/sdk/typescript/packages/react-components/src/components/link/Link.tsx similarity index 100% rename from ts-packages/react-components/src/components/link/Link.tsx rename to sdk/typescript/packages/react-components/src/components/link/Link.tsx diff --git a/ts-packages/react-components/src/components/logo/Logo.stories.tsx b/sdk/typescript/packages/react-components/src/components/logo/Logo.stories.tsx similarity index 100% rename from ts-packages/react-components/src/components/logo/Logo.stories.tsx rename to sdk/typescript/packages/react-components/src/components/logo/Logo.stories.tsx diff --git a/ts-packages/react-components/src/components/logo/LogoProps.ts b/sdk/typescript/packages/react-components/src/components/logo/LogoProps.ts similarity index 100% rename from ts-packages/react-components/src/components/logo/LogoProps.ts rename to sdk/typescript/packages/react-components/src/components/logo/LogoProps.ts diff --git a/ts-packages/react-components/src/components/logo/NymIcon.tsx b/sdk/typescript/packages/react-components/src/components/logo/NymIcon.tsx similarity index 100% rename from ts-packages/react-components/src/components/logo/NymIcon.tsx rename to sdk/typescript/packages/react-components/src/components/logo/NymIcon.tsx diff --git a/ts-packages/react-components/src/components/logo/NymLogo.tsx b/sdk/typescript/packages/react-components/src/components/logo/NymLogo.tsx similarity index 100% rename from ts-packages/react-components/src/components/logo/NymLogo.tsx rename to sdk/typescript/packages/react-components/src/components/logo/NymLogo.tsx diff --git a/ts-packages/react-components/src/components/logo/NymLogoBW.tsx b/sdk/typescript/packages/react-components/src/components/logo/NymLogoBW.tsx similarity index 100% rename from ts-packages/react-components/src/components/logo/NymLogoBW.tsx rename to sdk/typescript/packages/react-components/src/components/logo/NymLogoBW.tsx diff --git a/ts-packages/react-components/src/components/logo/NymWordmark.tsx b/sdk/typescript/packages/react-components/src/components/logo/NymWordmark.tsx similarity index 100% rename from ts-packages/react-components/src/components/logo/NymWordmark.tsx rename to sdk/typescript/packages/react-components/src/components/logo/NymWordmark.tsx diff --git a/ts-packages/react-components/src/components/mixnodes/IdentityKeyFormField.stories.tsx b/sdk/typescript/packages/react-components/src/components/mixnodes/IdentityKeyFormField.stories.tsx similarity index 100% rename from ts-packages/react-components/src/components/mixnodes/IdentityKeyFormField.stories.tsx rename to sdk/typescript/packages/react-components/src/components/mixnodes/IdentityKeyFormField.stories.tsx diff --git a/ts-packages/react-components/src/components/mixnodes/IdentityKeyFormField.tsx b/sdk/typescript/packages/react-components/src/components/mixnodes/IdentityKeyFormField.tsx similarity index 100% rename from ts-packages/react-components/src/components/mixnodes/IdentityKeyFormField.tsx rename to sdk/typescript/packages/react-components/src/components/mixnodes/IdentityKeyFormField.tsx diff --git a/ts-packages/react-components/src/components/networks/NetworkSelector.stories.tsx b/sdk/typescript/packages/react-components/src/components/networks/NetworkSelector.stories.tsx similarity index 100% rename from ts-packages/react-components/src/components/networks/NetworkSelector.stories.tsx rename to sdk/typescript/packages/react-components/src/components/networks/NetworkSelector.stories.tsx diff --git a/ts-packages/react-components/src/components/networks/NetworkSelector.tsx b/sdk/typescript/packages/react-components/src/components/networks/NetworkSelector.tsx similarity index 100% rename from ts-packages/react-components/src/components/networks/NetworkSelector.tsx rename to sdk/typescript/packages/react-components/src/components/networks/NetworkSelector.tsx diff --git a/ts-packages/react-components/src/components/password-strength/PasswordStrength.tsx b/sdk/typescript/packages/react-components/src/components/password-strength/PasswordStrength.tsx similarity index 100% rename from ts-packages/react-components/src/components/password-strength/PasswordStrength.tsx rename to sdk/typescript/packages/react-components/src/components/password-strength/PasswordStrength.tsx diff --git a/ts-packages/react-components/src/components/textfields/Mnemonic.tsx b/sdk/typescript/packages/react-components/src/components/textfields/Mnemonic.tsx similarity index 100% rename from ts-packages/react-components/src/components/textfields/Mnemonic.tsx rename to sdk/typescript/packages/react-components/src/components/textfields/Mnemonic.tsx diff --git a/ts-packages/react-components/src/components/textfields/Password.tsx b/sdk/typescript/packages/react-components/src/components/textfields/Password.tsx similarity index 100% rename from ts-packages/react-components/src/components/textfields/Password.tsx rename to sdk/typescript/packages/react-components/src/components/textfields/Password.tsx diff --git a/ts-packages/react-components/src/components/tooltip/Tooltip.stories.tsx b/sdk/typescript/packages/react-components/src/components/tooltip/Tooltip.stories.tsx similarity index 100% rename from ts-packages/react-components/src/components/tooltip/Tooltip.stories.tsx rename to sdk/typescript/packages/react-components/src/components/tooltip/Tooltip.stories.tsx diff --git a/ts-packages/react-components/src/components/tooltip/Tooltip.tsx b/sdk/typescript/packages/react-components/src/components/tooltip/Tooltip.tsx similarity index 100% rename from ts-packages/react-components/src/components/tooltip/Tooltip.tsx rename to sdk/typescript/packages/react-components/src/components/tooltip/Tooltip.tsx diff --git a/ts-packages/react-components/src/components/warnings/Error.tsx b/sdk/typescript/packages/react-components/src/components/warnings/Error.tsx similarity index 100% rename from ts-packages/react-components/src/components/warnings/Error.tsx rename to sdk/typescript/packages/react-components/src/components/warnings/Error.tsx diff --git a/ts-packages/react-components/src/hooks/useIsMounted.ts b/sdk/typescript/packages/react-components/src/hooks/useIsMounted.ts similarity index 100% rename from ts-packages/react-components/src/hooks/useIsMounted.ts rename to sdk/typescript/packages/react-components/src/hooks/useIsMounted.ts diff --git a/ts-packages/react-components/src/index.ts b/sdk/typescript/packages/react-components/src/index.ts similarity index 100% rename from ts-packages/react-components/src/index.ts rename to sdk/typescript/packages/react-components/src/index.ts diff --git a/ts-packages/react-components/src/playground/Playground.tsx b/sdk/typescript/packages/react-components/src/playground/Playground.tsx similarity index 100% rename from ts-packages/react-components/src/playground/Playground.tsx rename to sdk/typescript/packages/react-components/src/playground/Playground.tsx diff --git a/ts-packages/react-components/src/playground/buttons.tsx b/sdk/typescript/packages/react-components/src/playground/buttons.tsx similarity index 100% rename from ts-packages/react-components/src/playground/buttons.tsx rename to sdk/typescript/packages/react-components/src/playground/buttons.tsx diff --git a/ts-packages/react-components/src/playground/checkboxes.tsx b/sdk/typescript/packages/react-components/src/playground/checkboxes.tsx similarity index 100% rename from ts-packages/react-components/src/playground/checkboxes.tsx rename to sdk/typescript/packages/react-components/src/playground/checkboxes.tsx diff --git a/ts-packages/react-components/src/playground/fonts.tsx b/sdk/typescript/packages/react-components/src/playground/fonts.tsx similarity index 100% rename from ts-packages/react-components/src/playground/fonts.tsx rename to sdk/typescript/packages/react-components/src/playground/fonts.tsx diff --git a/ts-packages/react-components/src/playground/switches.tsx b/sdk/typescript/packages/react-components/src/playground/switches.tsx similarity index 100% rename from ts-packages/react-components/src/playground/switches.tsx rename to sdk/typescript/packages/react-components/src/playground/switches.tsx diff --git a/ts-packages/react-components/src/playground/theme.tsx b/sdk/typescript/packages/react-components/src/playground/theme.tsx similarity index 100% rename from ts-packages/react-components/src/playground/theme.tsx rename to sdk/typescript/packages/react-components/src/playground/theme.tsx diff --git a/ts-packages/react-components/src/playground/theme/MUIThemeExplorer.tsx b/sdk/typescript/packages/react-components/src/playground/theme/MUIThemeExplorer.tsx similarity index 100% rename from ts-packages/react-components/src/playground/theme/MUIThemeExplorer.tsx rename to sdk/typescript/packages/react-components/src/playground/theme/MUIThemeExplorer.tsx diff --git a/ts-packages/react-components/src/playground/theme/PaletteSwatches.tsx b/sdk/typescript/packages/react-components/src/playground/theme/PaletteSwatches.tsx similarity index 100% rename from ts-packages/react-components/src/playground/theme/PaletteSwatches.tsx rename to sdk/typescript/packages/react-components/src/playground/theme/PaletteSwatches.tsx diff --git a/ts-packages/react-components/src/stories/Introduction.stories.mdx b/sdk/typescript/packages/react-components/src/stories/Introduction.stories.mdx similarity index 100% rename from ts-packages/react-components/src/stories/Introduction.stories.mdx rename to sdk/typescript/packages/react-components/src/stories/Introduction.stories.mdx diff --git a/ts-packages/react-components/src/stories/Playground.stories.tsx b/sdk/typescript/packages/react-components/src/stories/Playground.stories.tsx similarity index 100% rename from ts-packages/react-components/src/stories/Playground.stories.tsx rename to sdk/typescript/packages/react-components/src/stories/Playground.stories.tsx diff --git a/ts-packages/react-webpack-with-theme-example/src/theme/mui-theme.d.ts b/sdk/typescript/packages/react-components/src/theme/mui-theme.d.ts similarity index 100% rename from ts-packages/react-webpack-with-theme-example/src/theme/mui-theme.d.ts rename to sdk/typescript/packages/react-components/src/theme/mui-theme.d.ts diff --git a/sdk/typescript/packages/react-components/src/typings/FC.d.ts b/sdk/typescript/packages/react-components/src/typings/FC.d.ts new file mode 100644 index 0000000000..08ebdfa298 --- /dev/null +++ b/sdk/typescript/packages/react-components/src/typings/FC.d.ts @@ -0,0 +1 @@ +declare type FCWithChildren

= React.FC>; diff --git a/ts-packages/react-components/src/typings/jpeg.d.ts b/sdk/typescript/packages/react-components/src/typings/jpeg.d.ts similarity index 100% rename from ts-packages/react-components/src/typings/jpeg.d.ts rename to sdk/typescript/packages/react-components/src/typings/jpeg.d.ts diff --git a/ts-packages/react-components/src/typings/json.d.ts b/sdk/typescript/packages/react-components/src/typings/json.d.ts similarity index 100% rename from ts-packages/react-components/src/typings/json.d.ts rename to sdk/typescript/packages/react-components/src/typings/json.d.ts diff --git a/ts-packages/react-components/src/typings/png.d.ts b/sdk/typescript/packages/react-components/src/typings/png.d.ts similarity index 100% rename from ts-packages/react-components/src/typings/png.d.ts rename to sdk/typescript/packages/react-components/src/typings/png.d.ts diff --git a/ts-packages/react-components/src/typings/svg.d.ts b/sdk/typescript/packages/react-components/src/typings/svg.d.ts similarity index 100% rename from ts-packages/react-components/src/typings/svg.d.ts rename to sdk/typescript/packages/react-components/src/typings/svg.d.ts diff --git a/ts-packages/react-components/tsconfig.eslint.json b/sdk/typescript/packages/react-components/tsconfig.eslint.json similarity index 100% rename from ts-packages/react-components/tsconfig.eslint.json rename to sdk/typescript/packages/react-components/tsconfig.eslint.json diff --git a/ts-packages/react-components/tsconfig.json b/sdk/typescript/packages/react-components/tsconfig.json similarity index 88% rename from ts-packages/react-components/tsconfig.json rename to sdk/typescript/packages/react-components/tsconfig.json index f35b798197..89d869a823 100644 --- a/ts-packages/react-components/tsconfig.json +++ b/sdk/typescript/packages/react-components/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../tsconfig.json", + "extends": "../../tsconfig.json", "compilerOptions": { "jsx": "react-jsx", "noEmit": true, diff --git a/sdk/typescript/packages/sdk-react/.eslintrc.json b/sdk/typescript/packages/sdk-react/.eslintrc.json new file mode 100644 index 0000000000..83e95d88a7 --- /dev/null +++ b/sdk/typescript/packages/sdk-react/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "parserOptions": { + "project": "./tsconfig.eslint.json" + } +} diff --git a/sdk/typescript/packages/sdk-react/README.md b/sdk/typescript/packages/sdk-react/README.md new file mode 100644 index 0000000000..ebc7451f0f --- /dev/null +++ b/sdk/typescript/packages/sdk-react/README.md @@ -0,0 +1,7 @@ +# Nym SDK React + +This package provides useful React components to interact with the Nym Mixnet: + +- a provider and hook to send messages over the Mixnet +- a provider and hook to manage Coconut credentials +- a provider and hook to sign and broadcast messages to send to the Nyx blockchain RPC nodes diff --git a/sdk/typescript/packages/sdk-react/package.json b/sdk/typescript/packages/sdk-react/package.json new file mode 100644 index 0000000000..4dcad819d5 --- /dev/null +++ b/sdk/typescript/packages/sdk-react/package.json @@ -0,0 +1,69 @@ +{ + "name": "@nymproject/sdk-react", + "version": "1.2.0-rc.2", + "license": "Apache-2.0", + "author": "Nym Technologies SA", + "files": [ + "dist/**/*" + ], + "browser": "dist/index.js", + "scripts": { + "build": "tsc --noEmit false", + "clean": "rimraf dist", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "tsc --noEmit true -w", + "storybook": "start-storybook -p 6006", + "storybook:build": "build-storybook", + "test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache", + "tsc": "tsc --noEmit true" + }, + "dependencies": { + "@nymproject/sdk": ">=1.2.0-rc.1 || ^1" + }, + "devDependencies": { + "@babel/core": "^7.17.5", + "@nymproject/eslint-config-react-typescript": "^1.0.0", + "@storybook/addon-actions": "^6.5.8", + "@storybook/addon-essentials": "^6.5.8", + "@storybook/addon-interactions": "^6.5.8", + "@storybook/addon-links": "^6.5.8", + "@storybook/builder-webpack5": "^6.5.8", + "@storybook/manager-webpack5": "^6.5.8", + "@storybook/react": "^6.5.15", + "@storybook/testing-library": "^0.0.9", + "@svgr/webpack": "^6.1.1", + "@types/flat": "^5.0.2", + "@types/react": "^18.0.26", + "@types/react-dom": "^18.0.10", + "@typescript-eslint/eslint-plugin": "^5.13.0", + "@typescript-eslint/parser": "^5.13.0", + "babel-loader": "^8.2.3", + "babel-plugin-root-import": "^5.1.0", + "eslint": "^8.10.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-airbnb-typescript": "^16.1.0", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-root-import": "^1.0.4", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^26.1.1", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-react": "^7.29.2", + "eslint-plugin-react-hooks": "^4.3.0", + "eslint-plugin-storybook": "^0.5.12", + "jest": "^27.1.0", + "prettier": "^2.8.7", + "rimraf": "^3.0.2", + "ts-jest": "^27.0.5", + "tsconfig-paths-webpack-plugin": "^3.5.2", + "typescript": "^4.6.2" + }, + "peerDependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "private": false, + "type": "module", + "types": "./dist/index.d.ts" +} diff --git a/sdk/typescript/packages/sdk-react/src/context/index.tsx b/sdk/typescript/packages/sdk-react/src/context/index.tsx new file mode 100644 index 0000000000..7e66b2c765 --- /dev/null +++ b/sdk/typescript/packages/sdk-react/src/context/index.tsx @@ -0,0 +1 @@ +export * from './mixnet'; diff --git a/sdk/typescript/packages/sdk-react/src/context/mixnet.tsx b/sdk/typescript/packages/sdk-react/src/context/mixnet.tsx new file mode 100644 index 0000000000..509e5893f7 --- /dev/null +++ b/sdk/typescript/packages/sdk-react/src/context/mixnet.tsx @@ -0,0 +1,109 @@ +import * as React from 'react'; +import { createNymMixnetClient, Events, MimeTypes, NymMixnetClient } from '@nymproject/sdk'; + +export interface BinaryMessageHeaders { + filename: string; + mimeType: string; +} + +export const parseBinaryMessageHeaders = (headers: string): BinaryMessageHeaders => + JSON.parse(headers) as BinaryMessageHeaders; + +interface State { + // data + isReady: boolean; + address?: string; + events?: Events; + + // methods + sendTextMessage: (args: { payload: string; recipient: string }) => Promise; + sendBinaryMessage: (args: { payload: Uint8Array; recipient: string; headers: BinaryMessageHeaders }) => Promise; +} + +const MixnetContext = React.createContext(undefined); + +export const useMixnetContext = (): State => { + const context = React.useContext(MixnetContext); + + if (!context) { + throw new Error('Please include a `import { MixnetContextProvider } from "./context"` before using this hook'); + } + + return context; +}; + +export const MixnetContextProvider: FCWithChildren<{ + clientId?: string; + nymApiUrl?: string; + preferredGatewayIdentityKey?: string; +}> = ({ + clientId = 'MyNymClientId', + nymApiUrl = 'https://validator.nymtech.net/api', + preferredGatewayIdentityKey = 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM', // this gateway has WSS + children, +}) => { + const [isReady, setReady] = React.useState(false); + const [address, setAddress] = React.useState(); + + const nym = React.useRef(null); + + React.useEffect(() => { + // on mount of the provider, create the client + (async () => { + nym.current = await createNymMixnetClient(); + if (nym.current?.events) { + nym.current.events.subscribeToConnected((e) => { + setAddress(e.args.address); + setReady(true); + }); + } + if (nym.current?.client) { + nym.current.client + .start({ + clientId, + nymApiUrl, + preferredGatewayIdentityKey, + }) + .catch((e) => console.error('Failed to start client', e)); + } + })(); + + // + }, []); + + const sendTextMessage = async (args: { payload: string; recipient: string }) => { + if (!nym.current?.client) { + console.error('Nym client has not initialised. Please wrap in useEffect on `isReady` prop of this context.'); + return; + } + await nym.current.client.send({ + recipient: args.recipient, + payload: { message: args.payload, mimeType: MimeTypes.TextPlain }, + }); + }; + + const sendBinaryMessage = async (args: { payload: Uint8Array; recipient: string; headers: BinaryMessageHeaders }) => { + if (!nym.current?.client) { + console.error('Nym client has not initialised. Please wrap in useEffect on `isReady` prop of this context.'); + return; + } + // convert headers to JSON + await nym.current.client.send({ + recipient: args.recipient, + payload: { message: args.payload, mimeType: 'application/octet-stream', headers: JSON.stringify(args.headers) }, + }); + }; + + const value = React.useMemo( + () => ({ + isReady, + events: nym.current?.events, + address, + sendTextMessage, + sendBinaryMessage, + }), + [isReady, nym.current, address], + ); + + return {children}; +}; diff --git a/sdk/typescript/packages/sdk-react/src/index.ts b/sdk/typescript/packages/sdk-react/src/index.ts new file mode 100644 index 0000000000..c38e8e8215 --- /dev/null +++ b/sdk/typescript/packages/sdk-react/src/index.ts @@ -0,0 +1 @@ +export * from './context'; diff --git a/sdk/typescript/packages/sdk-react/src/typings/FC.d.ts b/sdk/typescript/packages/sdk-react/src/typings/FC.d.ts new file mode 100644 index 0000000000..08ebdfa298 --- /dev/null +++ b/sdk/typescript/packages/sdk-react/src/typings/FC.d.ts @@ -0,0 +1 @@ +declare type FCWithChildren

= React.FC>; diff --git a/sdk/typescript/packages/sdk-react/tsconfig.eslint.json b/sdk/typescript/packages/sdk-react/tsconfig.eslint.json new file mode 100644 index 0000000000..3421e6f3c7 --- /dev/null +++ b/sdk/typescript/packages/sdk-react/tsconfig.eslint.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "jsx": "react-jsx", + "noEmit": true + }, + "include": [ + ".storybook/*.js", + "src/**/*.js", + "src/**/*.jsx", + "src/**/*.ts", + "src/**/*.tsx", + "src/**/*.stories.*", + ], + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/sdk/typescript/packages/sdk-react/tsconfig.json b/sdk/typescript/packages/sdk-react/tsconfig.json new file mode 100644 index 0000000000..89d869a823 --- /dev/null +++ b/sdk/typescript/packages/sdk-react/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "jsx": "react-jsx", + "noEmit": true, + "outDir": "./dist", + "declarationDir": "./dist" + }, + "include": [ + "src/**/*.ts", + "src/**/*.tsx" + ], + "exclude": [ + "node_modules", + "dist", + "src/stories", + "**/*.stories.*" + ] +} diff --git a/sdk/typescript/packages/sdk/.eslintrc.json b/sdk/typescript/packages/sdk/.eslintrc.json new file mode 100644 index 0000000000..83e95d88a7 --- /dev/null +++ b/sdk/typescript/packages/sdk/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "parserOptions": { + "project": "./tsconfig.eslint.json" + } +} diff --git a/sdk/typescript/packages/sdk/.gitignore b/sdk/typescript/packages/sdk/.gitignore index ed481bbc45..fbdf512d0d 100644 --- a/sdk/typescript/packages/sdk/.gitignore +++ b/sdk/typescript/packages/sdk/.gitignore @@ -1,3 +1,2 @@ src/mixnet/wasm/worker.js -src/mixnet/node-tester/worker.js -docs/ \ No newline at end of file +docs/ diff --git a/sdk/typescript/packages/sdk/README-CommonJS-full-fat.md b/sdk/typescript/packages/sdk/README-CommonJS-full-fat.md new file mode 100644 index 0000000000..8d5582a164 --- /dev/null +++ b/sdk/typescript/packages/sdk/README-CommonJS-full-fat.md @@ -0,0 +1,62 @@ +# Nym SDK (Typescript) CommonJS and ES5 + +``` +⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ +⚠ WARNING: ES5 & CommonJS with inline blobs ⚠ +⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ +``` + +### Please note: this is a CommonJS package targeting ES5. Use this for older projects or when you have bundling issues. It includes inline blobs that will interfere with CSPs that disallow them. + +If you are looking for an ESM version please use https://www.npmjs.com/package/@nymproject/sdk. + +---------------------------- + +The Nym SDK for Typescript will get you creating apps that can use the Nym Mixnet and Coconut credentials quickly. + +## TL;DR + +Include the SDK in your project: + +``` +npm install @nymproject/sdk-commonjs +``` + +Open a connection to a Gateway on the Nym Mixnet: + +```ts +import { createNymMixnetClient } from '@nymproject/sdk-commonjs'; + +const main = async () => { + const nym = await createNymMixnetClient(); + + const nymApiUrl = 'https://validator.nymtech.net/api'; + + // show message payload content when received + nym.events.subscribeToTextMessageReceivedEvent((e) => { + console.log('Got a message: ', e.args.payload); + }); + + // start the client and connect to a gateway + await nym.client.start({ + clientId: 'My awesome client', + nymApiUrl, + }); + + // send a message to yourself + const payload = 'Hello mixnet'; + const recipient = nym.client.selfAddress(); + nym.client.send({ payload, recipient }); + +}; +``` + +This will start the WASM client on a worker thread, so that your code can stay nice and snappy. + +Send a message to another user (you will need to know their address at a Gateway): + +```ts + const payload = 'Hello mixnet'; + const recipient = '<< RECIPIENT ADDRESS GOES HERE >>'; + await nym.client.send({ payload, recipient }); +``` diff --git a/sdk/typescript/packages/sdk/README-full-fat.md b/sdk/typescript/packages/sdk/README-full-fat.md new file mode 100644 index 0000000000..5abd214313 --- /dev/null +++ b/sdk/typescript/packages/sdk/README-full-fat.md @@ -0,0 +1,62 @@ +# Nym SDK (Typescript) + +``` +⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ +⚠ WARNING: ESM with inline blobs ⚠ +⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ +``` + +### Please note: this is a CommonJS package targeting ES5. Use this for older projects or when you have bundling issues. It includes inline blobs that will interfere with CSPs that disallow them. + +If you are looking for an ESM version please use https://www.npmjs.com/package/@nymproject/sdk. + +---------------------------- + +The Nym SDK for Typescript will get you creating apps that can use the Nym Mixnet and Coconut credentials quickly. + +## TL;DR + +Include the SDK in your project: + +``` +npm install @nymproject/sdk +``` + +Open a connection to a Gateway on the Nym Mixnet: + +```ts +import { createNymMixnetClient } from '@nymproject/sdk'; + +const main = async () => { + const nym = await createNymMixnetClient(); + + const nymApiUrl = 'https://validator.nymtech.net/api'; + + // show message payload content when received + nym.events.subscribeToTextMessageReceivedEvent((e) => { + console.log('Got a message: ', e.args.payload); + }); + + // start the client and connect to a gateway + await nym.client.start({ + clientId: 'My awesome client', + nymApiUrl, + }); + + // send a message to yourself + const payload = 'Hello mixnet'; + const recipient = nym.client.selfAddress(); + nym.client.send({ payload, recipient }); + +}; +``` + +This will start the WASM client on a worker thread, so that your code can stay nice and snappy. + +Send a message to another user (you will need to know their address at a Gateway): + +```ts + const payload = 'Hello mixnet'; + const recipient = '<< RECIPIENT ADDRESS GOES HERE >>'; + await nym.client.send({ payload, recipient }); +``` diff --git a/sdk/typescript/packages/sdk/package.json b/sdk/typescript/packages/sdk/package.json index 17d2c9d116..b6aa91c84b 100644 --- a/sdk/typescript/packages/sdk/package.json +++ b/sdk/typescript/packages/sdk/package.json @@ -1,45 +1,37 @@ { "name": "@nymproject/sdk", - "version": "1.1.9-rc0", + "version": "1.2.0-rc.2", "license": "Apache-2.0", "author": "Nym Technologies SA", - "type": "module", - "browser": "dist/esm/index.js", - "main": "dist/cjs/index.js", - "types": "./dist/esm/index.d.ts", "files": [ "dist/esm/worker.js", "dist/cjs/worker.js", "dist/**/*" ], + "main": "dist/cjs/index.js", + "browser": "dist/esm/index.js", "scripts": { - "start": "tsc -w", + "build": "scripts/build-prod.sh", + "build:dev": "scripts/build.sh", + "build:dev:esm": "scripts/build-dev-esm.sh", + "build:worker": "rollup -c rollup-worker.config.mjs", "clean": "rimraf dist", - "typecheck": "tsc --noEmit true", + "docs:dev": "run-p docs:watch docs:serve ", + "docs:generate": "typedoc", + "docs:generate:prod": "typedoc --basePath ./docs/tsdoc/nymproject/sdk/", + "docs:prod:build": "scripts/build-prod-docs-collect.sh", + "docs:serve": "reload -b -d ./docs -p 3000", + "docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\"", "lint": "eslint src", "lint:fix": "eslint src --fix", - "build:dependencies": "run-s build:dependencies:nym-client-wasm build:dependencies:ts-packages", - "build:dependencies:ts-packages": "cd ../../../.. && yarn && yarn build", - "build:dependencies:nym-client-wasm": "../nym-client-wasm/scripts/build.sh", - "prebuild": "yarn build:dependencies", - "build": "yarn build:only-this", - "build:only-this": "scripts/build-prod.sh", - "prebuild:dev": "yarn build:dependencies", - "build:dev": "yarn build:dev:only-this", - "build:dev:only-this": "scripts/build.sh", - "build:local": "run-s build:dependencies:nym-client-wasm build:dev:only-this", - "docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\"", - "docs:generate": "typedoc", - "docs:serve": "reload -b -d ./docs -p 3000", - "docs:dev": "run-p docs:watch docs:serve ", - "test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache" + "start": "tsc -w", + "start:dev": "nodemon --watch src -e ts,json --exec 'yarn build:dev:esm'", + "test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache", + "tsc": "tsc --noEmit true" }, "dependencies": { - "@npmcli/node-gyp": "^3.0.0", - "@nymproject/nym-client-wasm": "1", - "comlink": "^4.3.1", - "lerna": "^6.6.2", - "node-gyp": "^9.3.1" + "@nymproject/nym-client-wasm": ">=1.2.0-rc.0 || ^1", + "comlink": "^4.3.1" }, "devDependencies": { "@babel/core": "^7.15.0", @@ -55,6 +47,7 @@ "@rollup/plugin-replace": "^5.0.2", "@rollup/plugin-terser": "^0.2.1", "@rollup/plugin-typescript": "^10.0.1", + "@rollup/plugin-url": "^8.0.1", "@rollup/plugin-wasm": "^6.1.1", "@types/jest": "^27.0.1", "@types/node": "^16.7.13", @@ -79,7 +72,11 @@ "rollup-plugin-base64": "^1.0.1", "rollup-plugin-web-worker-loader": "^1.6.1", "ts-jest": "^29.1.0", + "ts-loader": "^9.4.2", "typedoc": "^0.24.8", "typescript": "^4.8.4" - } + }, + "private": false, + "type": "module", + "types": "./dist/esm/index.d.ts" } diff --git a/sdk/typescript/packages/sdk/rollup-cjs-full-fat.config.mjs b/sdk/typescript/packages/sdk/rollup-cjs-full-fat.config.mjs new file mode 100644 index 0000000000..d4c6e39e99 --- /dev/null +++ b/sdk/typescript/packages/sdk/rollup-cjs-full-fat.config.mjs @@ -0,0 +1,8 @@ +import { getConfig } from './rollup/cjs.mjs'; + +export default { + ...getConfig({ + inline: true, + outputDir: 'dist/cjs-full-fat', + }), +}; diff --git a/sdk/typescript/packages/sdk/rollup-cjs.config.mjs b/sdk/typescript/packages/sdk/rollup-cjs.config.mjs index 9f6d102d3d..a12e5bdb7a 100644 --- a/sdk/typescript/packages/sdk/rollup-cjs.config.mjs +++ b/sdk/typescript/packages/sdk/rollup-cjs.config.mjs @@ -1,23 +1,5 @@ -import typescript from '@rollup/plugin-typescript'; -import resolve from '@rollup/plugin-node-resolve'; -import { wasm } from '@rollup/plugin-wasm'; -import webWorkerLoader from 'rollup-plugin-web-worker-loader'; - -const extensions = ['.js', '.jsx', '.ts', '.tsx']; +import { getConfig } from './rollup/cjs.mjs'; export default { - input: 'src/index.ts', - output: { - dir: 'dist/cjs', - format: 'cjs', - }, - plugins: [ - webWorkerLoader({ targetPlatform: 'browser', inline: true }), - resolve({ extensions }), - wasm({ maxFileSize: 10000000, targetEnv: 'browser' }), - typescript({ - compilerOptions: { outDir: 'dist/cjs', target: 'es5' }, - exclude: ['mixnet/wasm/worker.ts', 'mixnet/node-tester/worker.ts'], - }), - ], + ...getConfig({ inline: false }), }; diff --git a/sdk/typescript/packages/sdk/rollup-esm-full-fat.config.mjs b/sdk/typescript/packages/sdk/rollup-esm-full-fat.config.mjs new file mode 100644 index 0000000000..ea80b1997b --- /dev/null +++ b/sdk/typescript/packages/sdk/rollup-esm-full-fat.config.mjs @@ -0,0 +1,8 @@ +import { getConfig } from './rollup/esm.mjs'; + +export default { + ...getConfig({ + inline: true, + outputDir: 'dist/esm-full-fat', + }), +}; diff --git a/sdk/typescript/packages/sdk/rollup-esm.config.mjs b/sdk/typescript/packages/sdk/rollup-esm.config.mjs index 3ad4c148fc..fa8d42b2ea 100644 --- a/sdk/typescript/packages/sdk/rollup-esm.config.mjs +++ b/sdk/typescript/packages/sdk/rollup-esm.config.mjs @@ -1,21 +1,7 @@ -import typescript from '@rollup/plugin-typescript'; -import resolve from '@rollup/plugin-node-resolve'; -import webWorkerLoader from 'rollup-plugin-web-worker-loader'; - -const extensions = ['.js', '.jsx', '.ts', '.tsx']; +import { getConfig } from './rollup/esm.mjs'; export default { - input: 'src/index.ts', - output: { - dir: 'dist/esm', - format: 'es', - }, - plugins: [ - webWorkerLoader({ targetPlatform: 'browser', inline: true }), - resolve({ extensions }), - typescript({ - exclude: ['mixnet/wasm/worker.ts', 'mixnet/node-tester/worker.ts'], - compilerOptions: { outDir: 'dist/esm' }, - }), - ], + ...getConfig({ + inline: false, + }), }; diff --git a/sdk/typescript/packages/sdk/rollup-worker.config.mjs b/sdk/typescript/packages/sdk/rollup-worker.config.mjs index e49bc592d4..61aab0b862 100644 --- a/sdk/typescript/packages/sdk/rollup-worker.config.mjs +++ b/sdk/typescript/packages/sdk/rollup-worker.config.mjs @@ -3,9 +3,7 @@ import resolve from '@rollup/plugin-node-resolve'; import { wasm } from '@rollup/plugin-wasm'; import replace from '@rollup/plugin-replace'; -const extensions = [ - '.js', '.jsx', '.ts', '.tsx', -]; +const extensions = ['.js', '.jsx', '.ts', '.tsx']; export default { input: 'src/mixnet/wasm/worker.ts', @@ -17,7 +15,7 @@ export default { resolve({ extensions }), // this is some nasty monkey patching that removes the WASM URL (because it is handled by the `wasm` plugin) replace({ - values: { 'input = new URL(\'nym_client_wasm_bg.wasm\', import.meta.url);': 'input = undefined;' }, + values: { "input = new URL('nym_client_wasm_bg.wasm', import.meta.url);": 'input = undefined;' }, delimiters: ['', ''], preventAssignment: true, }), diff --git a/sdk/typescript/packages/sdk/rollup/cjs.mjs b/sdk/typescript/packages/sdk/rollup/cjs.mjs new file mode 100644 index 0000000000..b08f3e0f0d --- /dev/null +++ b/sdk/typescript/packages/sdk/rollup/cjs.mjs @@ -0,0 +1,30 @@ +import typescript from '@rollup/plugin-typescript'; +import resolve from '@rollup/plugin-node-resolve'; +import { wasm } from '@rollup/plugin-wasm'; +import webWorkerLoader from 'rollup-plugin-web-worker-loader'; + +const extensions = ['.js', '.jsx', '.ts', '.tsx']; + +/** + * Gets the config for bundling the package as a CommonJS module. + * + * @param opts Options: + * `{ inline: boolean }` - set inline to true to inline the web worker in the main bundle + * `{ outputDir: string }` - override the destination + */ +export const getConfig = (opts) => ({ + input: 'src/index.ts', + output: { + dir: opts.outputDir || 'dist/cjs', + format: 'cjs', + }, + plugins: [ + webWorkerLoader({ targetPlatform: 'browser', inline: opts.inline }), // the inline param is used here + resolve({ extensions }), + wasm({ maxFileSize: 10000000, targetEnv: 'browser' }), + typescript({ + compilerOptions: { outDir: opts.outputDir || 'dist/cjs', target: 'es5' }, + exclude: ['mixnet/wasm/worker.ts'], + }), + ], +}); diff --git a/sdk/typescript/packages/sdk/rollup/esm.mjs b/sdk/typescript/packages/sdk/rollup/esm.mjs new file mode 100644 index 0000000000..29cd641793 --- /dev/null +++ b/sdk/typescript/packages/sdk/rollup/esm.mjs @@ -0,0 +1,28 @@ +import typescript from '@rollup/plugin-typescript'; +import resolve from '@rollup/plugin-node-resolve'; +import webWorkerLoader from 'rollup-plugin-web-worker-loader'; + +const extensions = ['.js', '.jsx', '.ts', '.tsx']; + +/** + * Gets the config for bundling the package as an ES Module. + * + * @param opts Options: + * `{ inline: boolean }` - set inline to true to inline the web worker in the main bundle + * `{ outputDir: string }` - override the destination * + */ +export const getConfig = (opts) => ({ + input: 'src/index.ts', + output: { + dir: opts.outputDir || 'dist/esm', + format: 'es', + }, + plugins: [ + webWorkerLoader({ targetPlatform: 'browser', inline: opts.inline }), // the inline param is used here + resolve({ extensions }), + typescript({ + exclude: ['mixnet/wasm/worker.ts'], + compilerOptions: { outDir: opts.outputDir || 'dist/esm' }, + }), + ], +}); diff --git a/sdk/typescript/packages/sdk/scripts/build-dev-esm.sh b/sdk/typescript/packages/sdk/scripts/build-dev-esm.sh new file mode 100755 index 0000000000..d7ce2b9af6 --- /dev/null +++ b/sdk/typescript/packages/sdk/scripts/build-dev-esm.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +#------------------------------------------------------- +# WEB WORKER (SDK WASM) +#------------------------------------------------------- +# The web worker needs to be bundled because the WASM bundle needs to be loaded synchronously and all dependencies +# must be included in the worker script (because it is not loaded as an ES Module) + +# build the worker +rollup -c rollup-worker.config.mjs + +# move it next to the Typescript `src/index.ts` so it can be inlined by rollup +cp dist/worker.js src/worker/worker.js || true +rm dist/worker.js || true + +#------------------------------------------------------- +# ESM +#------------------------------------------------------- + +# build the SDK as a ESM bundle +rollup -c rollup-esm.config.mjs + +#------------------------------------------------------- +# CLEAN UP +#------------------------------------------------------- + +#rm -rf dist/esm/worker + + diff --git a/sdk/typescript/packages/sdk/scripts/build-prod-docs-collect.sh b/sdk/typescript/packages/sdk/scripts/build-prod-docs-collect.sh new file mode 100755 index 0000000000..9cd137bcde --- /dev/null +++ b/sdk/typescript/packages/sdk/scripts/build-prod-docs-collect.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf ../../../../dist/ts/docs/tsdoc/nymproject/sdk || true + +# run the build +yarn docs:generate:prod + +# move the output outside of the yarn/npm workspaces +mkdir -p ../../../../dist/ts/docs/tsdoc/nymproject +mv docs ../../../../dist/ts/docs/tsdoc/nymproject/sdk + +echo "Output can be found in:" +realpath ../../../../dist/ts/docs/tsdoc/nymproject/sdk diff --git a/sdk/typescript/packages/sdk/scripts/build-prod.sh b/sdk/typescript/packages/sdk/scripts/build-prod.sh index f40998f1cc..1566948fd2 100755 --- a/sdk/typescript/packages/sdk/scripts/build-prod.sh +++ b/sdk/typescript/packages/sdk/scripts/build-prod.sh @@ -5,16 +5,16 @@ set -o nounset set -o pipefail rm -rf dist || true -rm -rf ../../../../dist || true +rm -rf ../../../../dist/ts/sdk/sdk || true # run the build scripts/build.sh node scripts/buildPackageJson.mjs # move the output outside of the yarn/npm workspaces -mkdir -p ../../../../dist -mv dist ../../../../dist -mv ../../../../dist/dist ../../../../dist/sdk +mkdir -p ../../../../dist/ts/sdk +mv dist ../../../../dist/ts/sdk +mv ../../../../dist/ts/sdk/dist ../../../../dist/ts/sdk/sdk echo "Output can be found in:" -realpath ../../../../dist/sdk +realpath ../../../../dist/ts/sdk/sdk diff --git a/sdk/typescript/packages/sdk/scripts/build.sh b/sdk/typescript/packages/sdk/scripts/build.sh index 05800b5c9d..bde7b47bdc 100755 --- a/sdk/typescript/packages/sdk/scripts/build.sh +++ b/sdk/typescript/packages/sdk/scripts/build.sh @@ -19,19 +19,6 @@ rollup -c rollup-worker.config.mjs rm -f src/mixnet/wasm/worker.js mv dist/worker.js src/mixnet/wasm/worker.js -#------------------------------------------------------- -# WEB WORKER (Node tester) -#------------------------------------------------------- -# The web worker needs to be bundled because the WASM bundle needs to be loaded synchronously and all dependencies -# must be included in the worker script (because it is not loaded as an ES Module) - -# build the worker -rollup -c rollup-node-tester-worker.config.mjs - -# move it next to the Typescript `mixnet/node-tester/index.ts` so it can be inlined by rollup -rm -f src/mixnet/node-tester/worker.js -mv dist/worker.js src/mixnet/node-tester/worker.js - #------------------------------------------------------- # ESM #------------------------------------------------------- @@ -49,11 +36,20 @@ rollup -c rollup-esm.config.mjs rollup -c rollup-cjs.config.mjs #------------------------------------------------------- -# FULL FAT +# ESM (full-fat) #------------------------------------------------------- -# build the SDK as a ESM bundle -rollup -c rollup-full-fat.config.mjs +# build the SDK as a ESM bundle (with worker inlined as a blob) +rollup -c rollup-esm-full-fat.config.mjs + +#------------------------------------------------------- +# COMMON JS (full-fat) +#------------------------------------------------------- +# Some old build systems cannot fully handle ESM or ES2021, so build +# a CommonJS bundle targeting ES5 + +# build the SDK as a CommonJS bundle (with worker inlined as a blob) +rollup -c rollup-cjs-full-fat.config.mjs #------------------------------------------------------- # CLEAN UP @@ -62,5 +58,7 @@ rollup -c rollup-full-fat.config.mjs # copy README cp README.md dist/esm cp README-CommonJS.md dist/cjs/README.md +cp README-full-fat.md dist/esm-full-fat +cp README-CommonJS-full-fat.md dist/cjs-full-fat/README.md diff --git a/sdk/typescript/packages/sdk/scripts/buildPackageJson.mjs b/sdk/typescript/packages/sdk/scripts/buildPackageJson.mjs index 91c9afd1b9..20026e5307 100644 --- a/sdk/typescript/packages/sdk/scripts/buildPackageJson.mjs +++ b/sdk/typescript/packages/sdk/scripts/buildPackageJson.mjs @@ -8,29 +8,20 @@ const browser = 'index.js'; const main = 'index.js'; const types = 'index.d.ts'; -// make a package.json for the CommonJS bundle -const packageJsonCommonJS = { - name: `${json.name}-commonjs`, +const getPackageJson = (type, suffix) => ({ + name: `${json.name}${suffix ? `-${suffix}`: ''}`, version: json.version, license: json.license, author: json.author, - type: 'commonjs', + type, browser, main, types, -}; +}); -// make a package.json for the ESM bundle -const packageJsonESM = { - name: json.name, - version: json.version, - license: json.license, - author: json.author, - type: 'module', - browser, - main, - types, -}; +fs.writeFileSync('dist/cjs/package.json', JSON.stringify(getPackageJson('commonjs', 'commonjs'), null, 2)); +fs.writeFileSync('dist/esm/package.json', JSON.stringify(getPackageJson('module'), null, 2)); + +fs.writeFileSync('dist/cjs-full-fat/package.json', JSON.stringify(getPackageJson('commonjs', 'commonjs-full-fat'), null, 2)); +fs.writeFileSync('dist/esm-full-fat/package.json', JSON.stringify(getPackageJson('module', 'full-fat'), null, 2)); -fs.writeFileSync('dist/cjs/package.json', JSON.stringify(packageJsonCommonJS, null, 2)); -fs.writeFileSync('dist/esm/package.json', JSON.stringify(packageJsonESM, null, 2)); diff --git a/sdk/typescript/packages/sdk/src/mixnet/index.ts b/sdk/typescript/packages/sdk/src/mixnet/index.ts index 2fb66914e6..3c4c661762 100644 --- a/sdk/typescript/packages/sdk/src/mixnet/index.ts +++ b/sdk/typescript/packages/sdk/src/mixnet/index.ts @@ -1,4 +1,2 @@ export * from './wasm'; export * from './wasm/types'; -export * from './node-tester'; -export * from './node-tester/types'; diff --git a/sdk/typescript/packages/sdk/src/mixnet/wasm/types-from-wasm-pack.ts b/sdk/typescript/packages/sdk/src/mixnet/wasm/types-from-wasm-pack.ts deleted file mode 100644 index 25fbba452c..0000000000 --- a/sdk/typescript/packages/sdk/src/mixnet/wasm/types-from-wasm-pack.ts +++ /dev/null @@ -1,336 +0,0 @@ -/** - */ -export interface TopologyWasm { - free(): void; - /** - * Specifies whether the client should not refresh the network topology after obtaining - * the first valid instance. - * Supersedes `topology_refresh_rate_ms`. - */ - disable_refreshing: boolean; - /** - * The uniform delay every which clients are querying the directory server - * to try to obtain a compatible network topology to send sphinx packets through. - */ - topology_refresh_rate_ms: bigint; - /** - * During topology refresh, test packets are sent through every single possible network - * path. This timeout determines waiting period until it is decided that the packet - * did not reach its destination. - */ - topology_resolution_timeout_ms: bigint; -} -/** - */ -export interface TrafficWasm { - free(): void; - /** - * The parameter of Poisson distribution determining how long, on average, - * sent packet is going to be delayed at any given mix node. - * So for a packet going through three mix nodes, on average, it will take three times this value - * until the packet reaches its destination. - */ - average_packet_delay_ms: bigint; - /** - * Controls whether the main packet stream constantly produces packets according to the predefined - * poisson distribution. - */ - disable_main_poisson_packet_distribution: boolean; - /** - * The parameter of Poisson distribution determining how long, on average, - * it is going to take another 'real traffic stream' message to be sent. - * If no real packets are available and cover traffic is enabled, - * a loop cover message is sent instead in order to preserve the rate. - */ - message_sending_average_delay_ms: bigint; - /** - * Controls whether the sent sphinx packet use the NON-DEFAULT bigger size. - */ - use_extended_packet_size: boolean; - /** - * Controls whether the sent packets should use outfox as opposed to the default sphinx. - */ - use_outfox: boolean; -} -/** - */ -export interface WasmGateway { - free(): void; - /** - */ - clients_port: number; - /** - */ - host: string; - /** - */ - identity_key: string; - /** - */ - mix_port: number; - /** - */ - owner: string; - /** - */ - sphinx_key: string; - /** - */ - version: string; -} - -/** - */ -export interface ReplySurbsWasm { - free(): void; - /** - * Defines the maximum number of reply surbs a remote party is allowed to request from this client at once. - */ - maximum_allowed_reply_surb_request_size: number; - /** - * Defines maximum amount of time given reply key is going to be valid for. - * This is going to be superseded by key rotation once implemented. - */ - maximum_reply_key_age_ms: bigint; - /** - * Defines maximum amount of time given reply surb is going to be valid for. - * This is going to be superseded by key rotation once implemented. - */ - maximum_reply_surb_age_ms: bigint; - /** - * Defines maximum amount of time the client is going to wait for reply surbs before - * deciding it's never going to get them and would drop all pending messages - */ - maximum_reply_surb_drop_waiting_period_ms: bigint; - /** - * Defines the maximum number of reply surbs the client would request. - */ - maximum_reply_surb_request_size: number; - /** - * Defines maximum amount of time the client is going to wait for reply surbs before explicitly asking - * for more even though in theory they wouldn't need to. - */ - maximum_reply_surb_rerequest_waiting_period_ms: bigint; - /** - * Defines the maximum number of reply surbs the client wants to keep in its storage at any times. - */ - maximum_reply_surb_storage_threshold: number; - /** - * Defines the minimum number of reply surbs the client would request. - */ - minimum_reply_surb_request_size: number; - /** - * Defines the minimum number of reply surbs the client wants to keep in its storage at all times. - * It can only allow to go below that value if its to request additional reply surbs. - */ - minimum_reply_surb_storage_threshold: number; -} - -/** - */ -export interface GatewayConnectionWasm { - free(): void; - /** - * How long we're willing to wait for a response to a message sent to the gateway, - * before giving up on it. - */ - gateway_response_timeout_ms: bigint; -} - -/** - */ -export interface AcknowledgementsWasm { - free(): void; - /** - * Value added to the expected round trip time of an acknowledgement packet before - * it is assumed it was lost and retransmission of the data packet happens. - * In an ideal network with 0 latency, this value would have been 0. - */ - ack_wait_addition_ms: bigint; - /** - * Value multiplied with the expected round trip time of an acknowledgement packet before - * it is assumed it was lost and retransmission of the data packet happens. - * In an ideal network with 0 latency, this value would have been 1. - */ - ack_wait_multiplier: number; - /** - * The parameter of Poisson distribution determining how long, on average, - * sent acknowledgement is going to be delayed at any given mix node. - * So for an ack going through three mix nodes, on average, it will take three times this value - * until the packet reaches its destination. - */ - average_ack_delay_ms: bigint; -} - -/** - */ -export interface CoverTrafficWasm { - free(): void; - /** - * Specifies the ratio of `primary_packet_size` to `secondary_packet_size` used in cover traffic. - * Only applicable if `secondary_packet_size` is enabled. - */ - cover_traffic_primary_size_ratio: number; - /** - * Controls whether the dedicated loop cover traffic stream should be enabled. - * (and sending packets, on average, every [Self::loop_cover_traffic_average_delay]) - */ - disable_loop_cover_traffic_stream: boolean; - /** - * The parameter of Poisson distribution determining how long, on average, - * it is going to take for another loop cover traffic message to be sent. - */ - loop_cover_traffic_average_delay_ms: bigint; -} - -export interface Config { - free(): void; -} - -export interface DebugWasm { - free(): void; - /** - * Defines all configuration options related to acknowledgements, such as delays or wait timeouts. - */ - acknowledgements: AcknowledgementsWasm; - /** - * Defines all configuration options related to cover traffic stream(s). - */ - cover_traffic: CoverTrafficWasm; - /** - * Defines all configuration options related to the gateway connection. - */ - gateway_connection: GatewayConnectionWasm; - /** - * Defines all configuration options related to reply SURBs. - */ - reply_surbs: ReplySurbsWasm; - /** - * Defines all configuration options related topology, such as refresh rates or timeouts. - */ - topology: TopologyWasm; - /** - * Defines all configuration options related to traffic streams. - */ - traffic: TrafficWasm; -} -/** - */ -export interface GatewayEndpointConfig { - free(): void; - /** - * gateway_id specifies ID of the gateway to which the client should send messages. - * If initially omitted, a random gateway will be chosen from the available topology. - */ - gateway_id: string; - /** - * Address of the gateway listener to which all client requests should be sent. - */ - gateway_listener: string; - /** - * Address of the gateway owner to which the client should send messages. - */ - gateway_owner: string; -} -/** - */ -export interface NymClient { - free(): void; - /** - * @returns {string} - */ - self_address(): string; - /** - * The simplest message variant where no additional information is attached. - * You're simply sending your `data` to specified `recipient` without any tagging. - * - * Ends up with `NymMessage::Plain` variant - * @param {Uint8Array} message - * @param {string} recipient - * @returns {Promise} - */ - send_regular_message(message: Uint8Array, recipient: string): Promise; - /** - * Creates a message used for a duplex anonymous communication where the recipient - * will never learn of our true identity. This is achieved by carefully sending `reply_surbs`. - * - * Note that if reply_surbs is set to zero then - * this variant requires the client having sent some reply_surbs in the past - * (and thus the recipient also knowing our sender tag). - * - * Ends up with `NymMessage::Repliable` variant - * @param {Uint8Array} message - * @param {string} recipient - * @param {number} reply_surbs - * @returns {Promise} - */ - send_anonymous_message(message: Uint8Array, recipient: string, reply_surbs: number): Promise; - /** - * Attempt to use our internally received and stored `ReplySurb` to send the message back - * to specified recipient whilst not knowing its full identity (or even gateway). - * - * Ends up with `NymMessage::Reply` variant - * @param {Uint8Array} message - * @param {string} recipient_tag - * @returns {Promise} - */ - send_reply(message: Uint8Array, recipient_tag: string): Promise; -} - -export interface Topology { - free(): void; - /** - * Specifies whether the client should not refresh the network topology after obtaining - * the first valid instance. - * Supersedes `topology_refresh_rate_ms`. - */ - disable_refreshing: boolean; - /** - * The uniform delay every which clients are querying the directory server - * to try to obtain a compatible network topology to send sphinx packets through. - */ - topology_refresh_rate_ms: bigint; - /** - * During topology refresh, test packets are sent through every single possible network - * path. This timeout determines waiting period until it is decided that the packet - * did not reach its destination. - */ - topology_resolution_timeout_ms: bigint; -} - -export interface Traffic { - free(): void; - /** - * The parameter of Poisson distribution determining how long, on average, - * sent packet is going to be delayed at any given mix node. - * So for a packet going through three mix nodes, on average, it will take three times this value - * until the packet reaches its destination. - */ - average_packet_delay_ms: bigint; - /** - * Controls whether the main packet stream constantly produces packets according to the predefined - * poisson distribution. - */ - disable_main_poisson_packet_distribution: boolean; - /** - * The parameter of Poisson distribution determining how long, on average, - * it is going to take another 'real traffic stream' message to be sent. - * If no real packets are available and cover traffic is enabled, - * a loop cover message is sent instead in order to preserve the rate. - */ - message_sending_average_delay_ms: bigint; - /** - * Controls whether the sent sphinx packet use the NON-DEFAULT bigger size. - */ - use_extended_packet_size: boolean; -} - -/** - */ -export interface NymClientBuilder { - free(): void; - /** - * @returns {Promise>} - */ - start_client(): Promise>; -} diff --git a/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts b/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts index 7df48ba73b..c395877f76 100644 --- a/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts +++ b/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts @@ -1,6 +1,4 @@ -import type { DebugWasm } from './types-from-wasm-pack'; - -export * from './types-from-wasm-pack'; +import type { DebugWasm } from '@nymproject/nym-client-wasm'; /** * diff --git a/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts b/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts index f1755b5d1f..90330f37b5 100644 --- a/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts +++ b/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts @@ -18,9 +18,7 @@ import wasmBytes from '@nymproject/nym-client-wasm/nym_client_wasm_bg.wasm'; import init, { NymClient, NymClientBuilder, - Config, - get_gateway, - default_debug, + ClientConfig, decode_payload, parse_utf8_string, utf8_string_to_byte_array, @@ -65,7 +63,7 @@ class ClientWrapper { /** * Creates the WASM client and initialises it. */ - init = (config: Config, onRawPayloadHandler?: OnRawPayloadFn) => { + init = (config: ClientConfig, onRawPayloadHandler?: OnRawPayloadFn) => { const onMessageHandler = (message: Uint8Array) => { try { if (onRawPayloadHandler) { @@ -161,14 +159,8 @@ init(wasmBytes()) const wrapper = new ClientWrapper(); const startHandler = async (config: NymClientConfig) => { - // fetch the gateway details (randomly chosen if no preferred gateway is set) - const gatewayEndpoint = await get_gateway(config.nymApiUrl, config.preferredGatewayIdentityKey); - - // set a different gatewayListener in order to avoid workaround ws over https error - if (config.gatewayListener) gatewayEndpoint.gateway_listener = config.gatewayListener; - // create the client, passing handlers for events - wrapper.init(new Config(config.clientId, config.nymApiUrl, config.debug || default_debug()), async (message) => { + wrapper.init(new ClientConfig(config), async (message) => { // fire an event with the raw message postMessageWithType({ kind: EventKinds.RawMessageReceived, diff --git a/sdk/typescript/packages/sdk/tsconfig.eslint.json b/sdk/typescript/packages/sdk/tsconfig.eslint.json new file mode 100644 index 0000000000..f7973eb336 --- /dev/null +++ b/sdk/typescript/packages/sdk/tsconfig.eslint.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true + }, + "include": [ + ".storybook/*.js", + "src/**/*.js", + "src/**/*.jsx", + "src/**/*.ts", + "src/**/*.tsx", + "src/**/*.stories.*", + "*.mjs", + ], + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/clients/validator/.eslintrc.json b/sdk/typescript/packages/validator-client/.eslintrc.json similarity index 100% rename from clients/validator/.eslintrc.json rename to sdk/typescript/packages/validator-client/.eslintrc.json diff --git a/clients/validator/.gitignore b/sdk/typescript/packages/validator-client/.gitignore similarity index 100% rename from clients/validator/.gitignore rename to sdk/typescript/packages/validator-client/.gitignore diff --git a/clients/validator/.npmignore b/sdk/typescript/packages/validator-client/.npmignore similarity index 100% rename from clients/validator/.npmignore rename to sdk/typescript/packages/validator-client/.npmignore diff --git a/clients/validator/.nvmrc b/sdk/typescript/packages/validator-client/.nvmrc similarity index 100% rename from clients/validator/.nvmrc rename to sdk/typescript/packages/validator-client/.nvmrc diff --git a/clients/validator/.nycrc.json b/sdk/typescript/packages/validator-client/.nycrc.json similarity index 100% rename from clients/validator/.nycrc.json rename to sdk/typescript/packages/validator-client/.nycrc.json diff --git a/clients/validator/.prettierrc b/sdk/typescript/packages/validator-client/.prettierrc similarity index 100% rename from clients/validator/.prettierrc rename to sdk/typescript/packages/validator-client/.prettierrc diff --git a/clients/validator/LICENSE b/sdk/typescript/packages/validator-client/LICENSE similarity index 100% rename from clients/validator/LICENSE rename to sdk/typescript/packages/validator-client/LICENSE diff --git a/clients/validator/README.md b/sdk/typescript/packages/validator-client/README.md similarity index 100% rename from clients/validator/README.md rename to sdk/typescript/packages/validator-client/README.md diff --git a/clients/validator/package.json b/sdk/typescript/packages/validator-client/package.json similarity index 93% rename from clients/validator/package.json rename to sdk/typescript/packages/validator-client/package.json index 386a94fe23..2f3eb4e02e 100644 --- a/clients/validator/package.json +++ b/sdk/typescript/packages/validator-client/package.json @@ -1,33 +1,31 @@ { "name": "@nymproject/nym-validator-client", - "version": "0.19.0", + "version": "1.2.0-rc.2", "description": "A TypeScript client for interacting with smart contracts in Nym validators", - "repository": "https://github.com/nymtech/nym", - "main": "dist/index.js", - "types": "dist/index.d.ts", - "scripts": { - "build": "rollup -c ./rollup.config.mjs", - "build:types": "rollup-type-bundler --dist ./dist", - "build:prod": "sh ./scripts/build-prod.sh", - "test": "ts-mocha -p ./tsconfig.test.json ./src/tests/**/*.test.ts", - "testmock": "ts-mocha -p ./tsconfig.test.json ./src/tests/mock/*.test.ts", - "coverage": "nyc npm test", - "clean": "rm -rf ./dist", - "lint": "eslint", - "lint:fix": "eslint --fix", - "lint:tsc": "tsc --noEmit", - "docs": "typedoc --out docs src/index.ts" - }, - "files": [ - "./dist/*" - ], - "keywords": [], + "license": "Apache-2.0", "author": "Nym Technologies SA (https://nymtech.net)", "contributors": [ "Dave Hrycyszyn (https://constructiveproof.com/)", "Jędrzej Stuczynski" ], - "license": "Apache-2.0", + "files": [ + "./dist/*" + ], + "main": "dist/index.js", + "repository": "https://github.com/nymtech/nym", + "scripts": { + "build": "rollup -c ./rollup.config.mjs", + "build:prod": "sh ./scripts/build-prod.sh", + "build:types": "rollup-type-bundler --dist ./dist", + "clean": "rm -rf ./dist", + "coverage": "nyc npm test", + "docs": "typedoc --out docs src/index.ts", + "lint": "eslint", + "lint:fix": "eslint --fix", + "test": "ts-mocha -p ./tsconfig.test.json ./src/tests/**/*.test.ts", + "testmock": "ts-mocha -p ./tsconfig.test.json ./src/tests/mock/*.test.ts", + "tsc": "tsc --noEmit" + }, "devDependencies": { "@cosmjs/cosmwasm-stargate": "^0.29.5", "@cosmjs/crypto": "^0.29.5", @@ -64,5 +62,7 @@ "ts-mocha": "^10.0.0", "typedoc": "^0.22.13", "typescript": "^4.6.2" - } -} + }, + "private": false, + "types": "dist/index.d.ts" +} \ No newline at end of file diff --git a/clients/validator/rollup.config.mjs b/sdk/typescript/packages/validator-client/rollup.config.mjs similarity index 100% rename from clients/validator/rollup.config.mjs rename to sdk/typescript/packages/validator-client/rollup.config.mjs diff --git a/clients/validator/scripts/build-prod.sh b/sdk/typescript/packages/validator-client/scripts/build-prod.sh similarity index 100% rename from clients/validator/scripts/build-prod.sh rename to sdk/typescript/packages/validator-client/scripts/build-prod.sh diff --git a/clients/validator/scripts/buildPackageJson.mjs b/sdk/typescript/packages/validator-client/scripts/buildPackageJson.mjs similarity index 100% rename from clients/validator/scripts/buildPackageJson.mjs rename to sdk/typescript/packages/validator-client/scripts/buildPackageJson.mjs diff --git a/clients/validator/src/currency.ts b/sdk/typescript/packages/validator-client/src/currency.ts similarity index 100% rename from clients/validator/src/currency.ts rename to sdk/typescript/packages/validator-client/src/currency.ts diff --git a/clients/validator/src/index.ts b/sdk/typescript/packages/validator-client/src/index.ts similarity index 100% rename from clients/validator/src/index.ts rename to sdk/typescript/packages/validator-client/src/index.ts diff --git a/clients/validator/src/nym-api-querier.ts b/sdk/typescript/packages/validator-client/src/nym-api-querier.ts similarity index 100% rename from clients/validator/src/nym-api-querier.ts rename to sdk/typescript/packages/validator-client/src/nym-api-querier.ts diff --git a/clients/validator/src/nyxd-querier.ts b/sdk/typescript/packages/validator-client/src/nyxd-querier.ts similarity index 100% rename from clients/validator/src/nyxd-querier.ts rename to sdk/typescript/packages/validator-client/src/nyxd-querier.ts diff --git a/clients/validator/src/query-client.ts b/sdk/typescript/packages/validator-client/src/query-client.ts similarity index 100% rename from clients/validator/src/query-client.ts rename to sdk/typescript/packages/validator-client/src/query-client.ts diff --git a/clients/validator/src/signing-client.ts b/sdk/typescript/packages/validator-client/src/signing-client.ts similarity index 100% rename from clients/validator/src/signing-client.ts rename to sdk/typescript/packages/validator-client/src/signing-client.ts diff --git a/clients/validator/src/stargate-helper.ts b/sdk/typescript/packages/validator-client/src/stargate-helper.ts similarity index 100% rename from clients/validator/src/stargate-helper.ts rename to sdk/typescript/packages/validator-client/src/stargate-helper.ts diff --git a/clients/validator/src/tests/expectedResponses.ts b/sdk/typescript/packages/validator-client/src/tests/expectedResponses.ts similarity index 100% rename from clients/validator/src/tests/expectedResponses.ts rename to sdk/typescript/packages/validator-client/src/tests/expectedResponses.ts diff --git a/clients/validator/src/tests/mock/client.ts b/sdk/typescript/packages/validator-client/src/tests/mock/client.ts similarity index 100% rename from clients/validator/src/tests/mock/client.ts rename to sdk/typescript/packages/validator-client/src/tests/mock/client.ts diff --git a/clients/validator/src/tests/mock/delegation.mock.test.ts b/sdk/typescript/packages/validator-client/src/tests/mock/delegation.mock.test.ts similarity index 100% rename from clients/validator/src/tests/mock/delegation.mock.test.ts rename to sdk/typescript/packages/validator-client/src/tests/mock/delegation.mock.test.ts diff --git a/clients/validator/src/tests/mock/gateway.mock.test.ts b/sdk/typescript/packages/validator-client/src/tests/mock/gateway.mock.test.ts similarity index 100% rename from clients/validator/src/tests/mock/gateway.mock.test.ts rename to sdk/typescript/packages/validator-client/src/tests/mock/gateway.mock.test.ts diff --git a/clients/validator/src/tests/mock/mixnet.mock.test.ts b/sdk/typescript/packages/validator-client/src/tests/mock/mixnet.mock.test.ts similarity index 100% rename from clients/validator/src/tests/mock/mixnet.mock.test.ts rename to sdk/typescript/packages/validator-client/src/tests/mock/mixnet.mock.test.ts diff --git a/clients/validator/src/tests/mock/mixnode.mock.test.ts b/sdk/typescript/packages/validator-client/src/tests/mock/mixnode.mock.test.ts similarity index 100% rename from clients/validator/src/tests/mock/mixnode.mock.test.ts rename to sdk/typescript/packages/validator-client/src/tests/mock/mixnode.mock.test.ts diff --git a/clients/validator/src/tests/mock/testData.ts b/sdk/typescript/packages/validator-client/src/tests/mock/testData.ts similarity index 100% rename from clients/validator/src/tests/mock/testData.ts rename to sdk/typescript/packages/validator-client/src/tests/mock/testData.ts diff --git a/clients/validator/src/tests/query/mixnetQueries.test.ts b/sdk/typescript/packages/validator-client/src/tests/query/mixnetQueries.test.ts similarity index 100% rename from clients/validator/src/tests/query/mixnetQueries.test.ts rename to sdk/typescript/packages/validator-client/src/tests/query/mixnetQueries.test.ts diff --git a/clients/validator/src/tests/query/vestingQueries.test.ts b/sdk/typescript/packages/validator-client/src/tests/query/vestingQueries.test.ts similarity index 100% rename from clients/validator/src/tests/query/vestingQueries.test.ts rename to sdk/typescript/packages/validator-client/src/tests/query/vestingQueries.test.ts diff --git a/clients/validator/src/tests/sign/mixnetActions.test.ts b/sdk/typescript/packages/validator-client/src/tests/sign/mixnetActions.test.ts similarity index 100% rename from clients/validator/src/tests/sign/mixnetActions.test.ts rename to sdk/typescript/packages/validator-client/src/tests/sign/mixnetActions.test.ts diff --git a/clients/validator/src/tests/simulate/simulateTx.test.ts b/sdk/typescript/packages/validator-client/src/tests/simulate/simulateTx.test.ts similarity index 100% rename from clients/validator/src/tests/simulate/simulateTx.test.ts rename to sdk/typescript/packages/validator-client/src/tests/simulate/simulateTx.test.ts diff --git a/clients/validator/src/types/global.d.ts b/sdk/typescript/packages/validator-client/src/types/global.d.ts similarity index 100% rename from clients/validator/src/types/global.d.ts rename to sdk/typescript/packages/validator-client/src/types/global.d.ts diff --git a/clients/validator/src/types/shared.ts b/sdk/typescript/packages/validator-client/src/types/shared.ts similarity index 100% rename from clients/validator/src/types/shared.ts rename to sdk/typescript/packages/validator-client/src/types/shared.ts diff --git a/clients/validator/src/types/simulate.ts b/sdk/typescript/packages/validator-client/src/types/simulate.ts similarity index 100% rename from clients/validator/src/types/simulate.ts rename to sdk/typescript/packages/validator-client/src/types/simulate.ts diff --git a/clients/validator/src/utils.ts b/sdk/typescript/packages/validator-client/src/utils.ts similarity index 100% rename from clients/validator/src/utils.ts rename to sdk/typescript/packages/validator-client/src/utils.ts diff --git a/clients/validator/tsconfig.json b/sdk/typescript/packages/validator-client/tsconfig.json similarity index 100% rename from clients/validator/tsconfig.json rename to sdk/typescript/packages/validator-client/tsconfig.json diff --git a/clients/validator/tsconfig.test.json b/sdk/typescript/packages/validator-client/tsconfig.test.json similarity index 100% rename from clients/validator/tsconfig.test.json rename to sdk/typescript/packages/validator-client/tsconfig.test.json diff --git a/sdk/typescript/scripts/build-prod-examples.sh b/sdk/typescript/scripts/build-prod-examples.sh new file mode 100755 index 0000000000..f93a4d764e --- /dev/null +++ b/sdk/typescript/scripts/build-prod-examples.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf dist/ts/examples || true +mkdir -p dist/ts/examples + +##--------------------------------------------------------------------------- +## ✅ Run this script from the root of the repository using `yarn sdk:build` +##--------------------------------------------------------------------------- + +packages=( +"chat-app/parcel" +"chat-app/plain-html" +"chat-app/react-webpack-with-theme-example" + +"chrome-extension" +"firefox-extension" + +"node-tester/parcel" +"node-tester/plain-html" +"node-tester/react" + +"react/mui-theme" +"react/sdk-react" +) + +pushd () { + command pushd "$@" > /dev/null +} + +popd () { + command popd "$@" > /dev/null +} + +echo "Summary of versions of examples to build:" +echo "" +pushd "sdk/typescript/examples" +for item in "${packages[@]}" +do + pushd "$item" + cat package.json | jq -r '. | "📦 " + .version + " " +.name' + popd +done diff --git a/sdk/typescript/scripts/build-prod-sdk.sh b/sdk/typescript/scripts/build-prod-sdk.sh new file mode 100755 index 0000000000..25a9828d60 --- /dev/null +++ b/sdk/typescript/scripts/build-prod-sdk.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf dist || true + +##--------------------------------------------------------------------------- +## ✅ Run this script from the root of the repository using `yarn sdk:build` +##--------------------------------------------------------------------------- + +# use wasm-pack to build packages +yarn build:wasm + +# build the Typescript SDK packages +yarn build:sdk + +# build documentation +cd sdk/typescript/docs +npm i +npm run docs:prod:build +cd ../../.. + +# build examples +pwd diff --git a/sdk/typescript/scripts/publish.sh b/sdk/typescript/scripts/publish.sh new file mode 100755 index 0000000000..d6eaeb6a84 --- /dev/null +++ b/sdk/typescript/scripts/publish.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +# ------------------------------------------------------- +# ✅ NB: Run this from the root of the repository +# ------------------------------------------------------- + +cd dist + +packages=( +chat-app/parcel +chat-app/plain-html +chat-app/react-webpack-with-theme-example +chrome-extension +firefox-extension +node-tester/parcel +node-tester/plain-html +node-tester/react +react/mui-theme +react/sdk-react +) + +pushd () { + command pushd "$@" > /dev/null +} + +popd () { + command popd "$@" > /dev/null +} + +echo "Summary of versions of packages to publish:" +echo "" +for item in "${packages[@]}" +do + pushd "$item" + cat package.json | jq -r '. | "📦 " + .version + " " +.name' + popd +done + +echo "" +echo "" + +for item in "${packages[@]}" +do + pushd "$item" + echo "🚀 Publishing $item..." + cat package.json | jq -r '. | .name + " " +.version' + npm publish --access=public + popd + echo "" +done +echo "" +echo "✅ Done" + diff --git a/sdk/typescript/scripts/unpublish.sh b/sdk/typescript/scripts/unpublish.sh new file mode 100755 index 0000000000..99ef7b5e25 --- /dev/null +++ b/sdk/typescript/scripts/unpublish.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +cd dist + +packages=( +"ts/sdk/node-tester/cjs" +"ts/sdk/node-tester/cjs-full-fat" +"ts/sdk/node-tester/esm" +"ts/sdk/node-tester/esm-full-fat" +) +packages2=( +"wasm/client" +"wasm/mix-fetch" +"wasm/node-tester" +"wasm/extension-storage" + +"ts/sdk/mix-fetch/cjs" +"ts/sdk/mix-fetch/cjs-full-fat" +"ts/sdk/mix-fetch/esm" +"ts/sdk/mix-fetch/esm-full-fat" + +"ts/sdk/node-tester/cjs" +"ts/sdk/node-tester/cjs-full-fat" +"ts/sdk/node-tester/esm" +"ts/sdk/node-tester/esm-full-fat" + +"ts/sdk/sdk/cjs" +"ts/sdk/sdk/cjs-full-fat" +"ts/sdk/sdk/esm" +"ts/sdk/sdk/esm-full-fat" +) + +pushd () { + command pushd "$@" > /dev/null +} + +popd () { + command popd "$@" > /dev/null +} + +echo "Summary of versions of packages to publish:" +echo "" +for item in "${packages[@]}" +do + pushd "$item" + cat package.json | jq -r '. | "📦 " + .version + " " +.name' + popd +done + +echo "" +echo "" + +for item in "${packages[@]}" +do + pushd "$item" + echo "🚀 Publishing $item..." + VERSION_SPEC=$(cat package.json | jq -r '. | .name + "@" +.version') + npm publish --access=public + popd + echo "" +done +echo "" +echo "✅ Done" + diff --git a/service-providers/common/examples/control_requests.rs b/service-providers/common/examples/control_requests.rs index 14886390f8..9deb9cebd0 100644 --- a/service-providers/common/examples/control_requests.rs +++ b/service-providers/common/examples/control_requests.rs @@ -36,7 +36,7 @@ async fn main() -> anyhow::Result<()> { // but I needed an easy way of sending to and receiving from the mixnet // and that was the most straightforward way of achieving it let mut client = MixnetClient::connect_new().await.unwrap(); - let provider: Recipient = "AN8eLxYWFitCkMn92zim3PrPszxJZDYyFFKP7qnnAAew.8UAxL3LwQBis6WpM3GGXaqKGaVdnLCpGJWumHT6KNdTH@77TSuVU8d1oXKbPzjec2xh4i3Wj5WwUyy9Lr36sm8gZm".parse().unwrap(); + let provider: Recipient = "8YF6f8x17j3fviBdU87EGD9g9MAgn9DARxunwLEVM7Bm.4ydfpjbTjCmzj58hWdQjxU2gT6CRVnTbnKajr2hAGBBM@2xU4CBE6QiiYt6EyBXSALwxkNvM7gqJfjHXaMkjiFmYW".parse().unwrap(); // generic service provider request, so we don't even need to care it's to the socks5 provider let request_health = ControlRequest::Health; diff --git a/service-providers/common/src/interface/version.rs b/service-providers/common/src/interface/version.rs index 906846d438..e27bc08809 100644 --- a/service-providers/common/src/interface/version.rs +++ b/service-providers/common/src/interface/version.rs @@ -54,7 +54,7 @@ macro_rules! define_simple_version { } impl $name { - pub fn new(use_legacy: bool) -> Self { + pub const fn new(use_legacy: bool) -> Self { if use_legacy { Self::new_legacy() } else { @@ -62,23 +62,23 @@ macro_rules! define_simple_version { } } - pub fn new_legacy() -> Self { + pub const fn new_legacy() -> Self { $name::Legacy } - pub fn new_versioned(version: u8) -> Self { + pub const fn new_versioned(version: u8) -> Self { $name::Versioned(version) } - pub fn new_current() -> Self { + pub const fn new_current() -> Self { $name::new(false) } - pub fn is_legacy(&self) -> bool { + pub const fn is_legacy(&self) -> bool { matches!(self, $name::Legacy) } - pub fn as_u8(&self) -> Option { + pub const fn as_u8(&self) -> Option { match self { $name::Legacy => None, $name::Versioned(version) => Some(*version), diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index 67ed6b41fa..88c1446563 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-network-requester" -version = "1.1.28" +version = "1.1.29" authors.workspace = true edition.workspace = true rust-version = "1.65" diff --git a/service-providers/network-requester/src/cli/init.rs b/service-providers/network-requester/src/cli/init.rs index 9cd092fc89..24b887c039 100644 --- a/service-providers/network-requester/src/cli/init.rs +++ b/service-providers/network-requester/src/cli/init.rs @@ -27,6 +27,19 @@ pub(crate) struct Init { #[arg(long)] id: String, + /// Specifies whether this network requester should run in 'open-proxy' mode + #[arg(long)] + open_proxy: Option, + + /// Enable service anonymized statistics that get sent to a statistics aggregator server + #[arg(long)] + enable_statistics: Option, + + /// Mixnet client address where a statistics aggregator is running. The default value is a Nym + /// aggregator client + #[arg(long)] + statistics_recipient: Option, + /// Id of the gateway we are going to connect to. #[arg(long)] gateway: Option, @@ -66,9 +79,11 @@ impl From for OverrideConfig { fastmode: false, no_cover: false, medium_toggle: false, - nyxd_urls: init_config.nyxd_urls, enabled_credentials_mode: init_config.enabled_credentials_mode, + open_proxy: init_config.open_proxy, + enable_statistics: init_config.enabled_credentials_mode, + statistics_recipient: init_config.statistics_recipient, } } } diff --git a/service-providers/network-requester/src/cli/mod.rs b/service-providers/network-requester/src/cli/mod.rs index 98106b3ca7..8a2140166e 100644 --- a/service-providers/network-requester/src/cli/mod.rs +++ b/service-providers/network-requester/src/cli/mod.rs @@ -19,6 +19,7 @@ use nym_client_core::client::base_client::storage::gateway_details::{ use nym_client_core::client::key_manager::persistence::OnDiskKeys; use nym_client_core::config::GatewayEndpointConfig; use nym_client_core::error::ClientCoreError; +use nym_config::OptionalSet; use nym_sphinx::params::PacketSize; mod build_info; @@ -81,6 +82,10 @@ pub(crate) struct OverrideConfig { medium_toggle: bool, nyxd_urls: Option>, enabled_credentials_mode: Option, + + open_proxy: Option, + enable_statistics: Option, + statistics_recipient: Option, } pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config { @@ -126,6 +131,9 @@ pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config { BaseClientConfig::with_disabled_credentials, args.enabled_credentials_mode.map(|b| !b), ) + .with_optional(Config::with_open_proxy, args.open_proxy) + .with_optional(Config::with_enabled_statistics, args.enable_statistics) + .with_optional(Config::with_statistics_recipient, args.statistics_recipient) } pub(crate) async fn execute(args: Cli) -> Result<(), NetworkRequesterError> { @@ -179,7 +187,7 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result { let updated_step1: ConfigV1_1_20 = old_config.into(); let updated_step2: ConfigV1_1_20_2 = updated_step1.into(); - let (updated, gateway_config) = updated_step2.upgrade(); + let (updated, gateway_config) = updated_step2.upgrade()?; persist_gateway_details(&updated, gateway_config)?; updated.save_to_default_location()?; @@ -201,7 +209,7 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result { info!("It is going to get updated to the current specification."); let updated_step1: ConfigV1_1_20_2 = old_config.into(); - let (updated, gateway_config) = updated_step1.upgrade(); + let (updated, gateway_config) = updated_step1.upgrade()?; persist_gateway_details(&updated, gateway_config)?; updated.save_to_default_location()?; @@ -220,7 +228,7 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result info!("It seems the client is using <= v1.1.20_2 config template."); info!("It is going to get updated to the current specification."); - let (updated, gateway_config) = old_config.upgrade(); + let (updated, gateway_config) = old_config.upgrade()?; persist_gateway_details(&updated, gateway_config)?; updated.save_to_default_location()?; diff --git a/service-providers/network-requester/src/cli/run.rs b/service-providers/network-requester/src/cli/run.rs index 4e5cee9c47..a2ca949675 100644 --- a/service-providers/network-requester/src/cli/run.rs +++ b/service-providers/network-requester/src/cli/run.rs @@ -8,7 +8,6 @@ use crate::{ }; use clap::Args; use log::error; -use nym_sphinx::addressing::clients::Recipient; const ENABLE_STATISTICS: &str = "enable-statistics"; @@ -21,11 +20,11 @@ pub(crate) struct Run { /// Specifies whether this network requester should run in 'open-proxy' mode #[arg(long)] - open_proxy: bool, + open_proxy: Option, /// Enable service anonymized statistics that get sent to a statistics aggregator server #[arg(long)] - enable_statistics: bool, + enable_statistics: Option, /// Mixnet client address where a statistics aggregator is running. The default value is a Nym /// aggregator client @@ -61,12 +60,19 @@ impl From for OverrideConfig { medium_toggle: run_config.medium_toggle, nyxd_urls: None, enabled_credentials_mode: run_config.enabled_credentials_mode, + open_proxy: run_config.open_proxy, + enable_statistics: run_config.enabled_credentials_mode, + statistics_recipient: run_config.statistics_recipient, } } } pub(crate) async fn execute(args: &Run) -> Result<(), NetworkRequesterError> { - if args.open_proxy { + let mut config = try_load_current_config(&args.id)?; + config = override_config(config, OverrideConfig::from(args.clone())); + log::debug!("Using config: {:#?}", config); + + if config.network_requester.open_proxy { println!( "\n\nYOU HAVE STARTED IN 'OPEN PROXY' MODE. ANYONE WITH YOUR CLIENT ADDRESS \ CAN MAKE REQUESTS FROM YOUR MACHINE. PLEASE QUIT IF YOU DON'T UNDERSTAND WHAT \ @@ -74,7 +80,7 @@ pub(crate) async fn execute(args: &Run) -> Result<(), NetworkRequesterError> { ); } - if args.enable_statistics { + if config.network_requester.enabled_statistics { println!( "\n\nTHE NETWORK REQUESTER STATISTICS ARE ENABLED. IT WILL COLLECT AND SEND \ ANONYMIZED STATISTICS TO A CENTRAL SERVER. PLEASE QUIT IF YOU DON'T WANT \ @@ -82,32 +88,12 @@ pub(crate) async fn execute(args: &Run) -> Result<(), NetworkRequesterError> { ); } - let mut config = try_load_current_config(&args.id)?; - config = override_config(config, OverrideConfig::from(args.clone())); - log::debug!("Using config: {:#?}", config); - if !version_check(&config) { error!("failed the local version check"); return Err(NetworkRequesterError::FailedLocalVersionCheck); } - // TODO: consider incorporating statistics_recipient, open_proxy and enable_statistics in - // `Config`. - - let stats_provider_addr = args - .statistics_recipient - .as_ref() - .map(Recipient::try_from_base58_string) - .transpose() - .unwrap_or(None); - log::info!("Starting socks5 service provider"); - let server = crate::core::NRServiceProviderBuilder::new( - config, - args.open_proxy, - args.enable_statistics, - stats_provider_addr, - ) - .await; + let server = crate::core::NRServiceProviderBuilder::new(config).await; server.run_service_provider().await } diff --git a/service-providers/network-requester/src/config/mod.rs b/service-providers/network-requester/src/config/mod.rs index e4ba1fa9da..0298d6caaa 100644 --- a/service-providers/network-requester/src/config/mod.rs +++ b/service-providers/network-requester/src/config/mod.rs @@ -112,6 +112,24 @@ impl Config { self.base.validate() } + #[must_use] + pub fn with_open_proxy(mut self, open_proxy: bool) -> Self { + self.network_requester.open_proxy = open_proxy; + self + } + + #[must_use] + pub fn with_enabled_statistics(mut self, enabled_statistics: bool) -> Self { + self.network_requester.enabled_statistics = enabled_statistics; + self + } + + #[must_use] + pub fn with_statistics_recipient(mut self, statistics_recipient: String) -> Self { + self.network_requester.statistics_recipient = Some(statistics_recipient); + self + } + // poor man's 'builder' method pub fn with_base(mut self, f: F, val: T) -> Self where @@ -162,12 +180,28 @@ impl Config { #[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] #[serde(default, deny_unknown_fields)] pub struct NetworkRequester { + /// specifies whether this network requester should run in 'open-proxy' mode + /// and thus would attempt to resolve **ANY** request it receives. + pub open_proxy: bool, + + /// specifies whether this network requester would send anonymized statistics to a statistics aggregator server + pub enabled_statistics: bool, + + /// in case of enabled statistics, specifies mixnet client address where a statistics aggregator is running + pub statistics_recipient: Option, + + /// Disable Poisson sending rate, and only send cover traffic occasionally as keepalive messages. + /// This is equivalent to setting debug.traffic.disable_main_poisson_packet_distribution = true, + /// and debug.cover_traffic.loop_cover_traffic_average_delay = 5s. pub disable_poisson_rate: bool, } impl Default for NetworkRequester { fn default() -> Self { NetworkRequester { + open_proxy: false, + enabled_statistics: false, + statistics_recipient: None, disable_poisson_rate: true, } } diff --git a/service-providers/network-requester/src/config/old_config_v1_1_20_2.rs b/service-providers/network-requester/src/config/old_config_v1_1_20_2.rs index 280d6e1ec1..68cd8031ec 100644 --- a/service-providers/network-requester/src/config/old_config_v1_1_20_2.rs +++ b/service-providers/network-requester/src/config/old_config_v1_1_20_2.rs @@ -1,8 +1,14 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::persistence::NetworkRequesterPaths; -use crate::config::{default_config_filepath, Config, Debug, NetworkRequester}; +use crate::{ + config::{ + default_config_filepath, persistence::NetworkRequesterPaths, Config, Debug, + NetworkRequester, + }, + error::NetworkRequesterError, +}; + use log::trace; use nym_bin_common::logging::LoggingSettings; use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2; @@ -58,7 +64,7 @@ impl ConfigV1_1_20_2 { // in this upgrade, gateway endpoint configuration was moved out of the config file, // so its returned to be stored elsewhere. - pub fn upgrade(self) -> (Config, GatewayEndpointConfig) { + pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig), NetworkRequesterError> { trace!("Upgrading from v1.1.20_2"); let gateway_details = self.base.client.gateway_endpoint.clone().into(); let nr_description = self @@ -72,7 +78,7 @@ impl ConfigV1_1_20_2 { let config = Config { base: self.base.into(), storage_paths: NetworkRequesterPaths { - common_paths: self.storage_paths.common_paths.upgrade_default(), + common_paths: self.storage_paths.common_paths.upgrade_default()?, allowed_list_location: self.storage_paths.allowed_list_location, unknown_list_location: self.storage_paths.unknown_list_location, nr_description, @@ -82,7 +88,7 @@ impl ConfigV1_1_20_2 { network_requester: self.network_requester.into(), }; - (config, gateway_details) + Ok((config, gateway_details)) } } diff --git a/service-providers/network-requester/src/config/template.rs b/service-providers/network-requester/src/config/template.rs index 567793c064..1c701f5f94 100644 --- a/service-providers/network-requester/src/config/template.rs +++ b/service-providers/network-requester/src/config/template.rs @@ -81,12 +81,21 @@ nr_description = '{{ storage_paths.nr_description }}' [network_requester] +# specifies whether this network requester should run in 'open-proxy' mode +# and thus would attempt to resolve **ANY** request it receives. +open_proxy = {{ network_requester.open_proxy }} + +# specifies whether this network requester would send anonymized statistics to a statistics aggregator server +enabled_statistics = {{ network_requester.enabled_statistics }} + +# in case of enabled statistics, specifies mixnet client address where a statistics aggregator is running +statistics_recipient = '{{ network_requester.statistics_recipient }}' + # Disable Poisson sending rate, and only send cover traffic occasionally as keepalive messages. # This is equivalent to setting debug.traffic.disable_main_poisson_packet_distribution = true, # and debug.cover_traffic.loop_cover_traffic_average_delay = 5s. disable_poisson_rate = {{ network_requester.disable_poisson_rate }} - ##### logging configuration options ##### [logging] diff --git a/service-providers/network-requester/src/core.rs b/service-providers/network-requester/src/core.rs index cd9b57f2dd..8d743e3c03 100644 --- a/service-providers/network-requester/src/core.rs +++ b/service-providers/network-requester/src/core.rs @@ -53,9 +53,6 @@ pub(crate) fn new_legacy_request_version() -> RequestVersion { pub struct NRServiceProviderBuilder { config: Config, outbound_request_filter: OutboundRequestFilter, - open_proxy: bool, - enable_statistics: bool, - stats_provider_addr: Option, standard_list: StandardList, allowed_hosts: StoredAllowedHosts, } @@ -64,7 +61,6 @@ struct NRServiceProvider { config: Config, outbound_request_filter: OutboundRequestFilter, - open_proxy: bool, mixnet_client: nym_sdk::mixnet::MixnetClient, controller_sender: ControllerSender, @@ -82,6 +78,7 @@ impl ServiceProvider for NRServiceProvider { sender: Option, request: Request, ) -> Result<(), Self::ServiceProviderError> { + log::debug!("on_request {:?}", request); if let Some(response) = self.handle_request(sender, request).await? { // TODO: this (i.e. `reply::MixnetAddress`) should be incorporated into the actual interface if let Some(return_address) = reply::MixnetAddress::new(None, sender) { @@ -112,6 +109,8 @@ impl ServiceProvider for NRServiceProvider { request: Socks5Request, interface_version: ProviderInterfaceVersion, ) -> Result, Self::ServiceProviderError> { + log::debug!("handle_provider_data_request {:?}", request); + // TODO: streamline this a bit more let request_version = RequestVersion::new(interface_version, request.protocol_version); @@ -158,12 +157,7 @@ impl ServiceProvider for NRServiceProvider { } impl NRServiceProviderBuilder { - pub async fn new( - config: Config, - open_proxy: bool, - enable_statistics: bool, - stats_provider_addr: Option, - ) -> NRServiceProviderBuilder { + pub async fn new(config: Config) -> NRServiceProviderBuilder { let standard_list = StandardList::new(); let allowed_hosts = StoredAllowedHosts::new(&config.storage_paths.allowed_list_location); @@ -176,9 +170,6 @@ impl NRServiceProviderBuilder { NRServiceProviderBuilder { config, outbound_request_filter, - open_proxy, - enable_statistics, - stats_provider_addr, standard_list, allowed_hosts, } @@ -186,6 +177,15 @@ impl NRServiceProviderBuilder { /// Start all subsystems pub async fn run_service_provider(self) -> Result<(), NetworkRequesterError> { + let stats_provider_addr = self + .config + .network_requester + .statistics_recipient + .as_ref() + .map(Recipient::try_from_base58_string) + .transpose() + .unwrap_or(None); + // Connect to the mixnet let mixnet_client = create_mixnet_client(&self.config.base, &self.config.storage_paths.common_paths) @@ -208,9 +208,9 @@ impl NRServiceProviderBuilder { active_connections_controller.run().await; }); - let stats_collector = if self.enable_statistics { + let stats_collector = if self.config.network_requester.enabled_statistics { let stats_collector = - ServiceStatisticsCollector::new(self.stats_provider_addr, mix_input_sender.clone()) + ServiceStatisticsCollector::new(stats_provider_addr, mix_input_sender.clone()) .await .expect("Service statistics collector could not be bootstrapped"); let mut stats_sender = StatisticsSender::new(stats_collector.clone()); @@ -253,7 +253,6 @@ impl NRServiceProviderBuilder { let service_provider = NRServiceProvider { config: self.config, outbound_request_filter: self.outbound_request_filter, - open_proxy: self.open_proxy, mixnet_client, controller_sender, mix_input_sender, @@ -434,7 +433,8 @@ impl NRServiceProvider { let remote_addr = connect_req.remote_addr; let conn_id = connect_req.conn_id; - if !self.open_proxy && !self.outbound_request_filter.check(&remote_addr).await { + let open_proxy = self.config.network_requester.open_proxy; + if !open_proxy && !self.outbound_request_filter.check(&remote_addr).await { let log_msg = format!("Domain {remote_addr:?} failed filter check"); log::info!("{}", log_msg); let msg = MixnetMessage::new_connection_error( @@ -488,10 +488,11 @@ impl NRServiceProvider { query: QueryRequest, ) -> Result, NetworkRequesterError> { let protocol_version = Socks5ProtocolVersion::default(); + let response = match query { QueryRequest::OpenProxy => Socks5Response::new_query( protocol_version, - QueryResponse::OpenProxy(self.open_proxy), + QueryResponse::OpenProxy(self.config.network_requester.open_proxy), ), QueryRequest::Description => Socks5Response::new_query( protocol_version, diff --git a/service-providers/network-requester/src/reply.rs b/service-providers/network-requester/src/reply.rs index 7aba7473d1..e3eac3a03c 100644 --- a/service-providers/network-requester/src/reply.rs +++ b/service-providers/network-requester/src/reply.rs @@ -140,9 +140,6 @@ impl MixnetMessage { data: Vec, closed_socket: bool, ) -> Self { - if seq == 0 && data.is_empty() { - println!("new empty response with 0 seq") - } let response_content = SocketData::new(seq, connection_id, closed_socket, data); Self::new_network_data_response(address, request_version, connection_id, response_content) } diff --git a/service-providers/network-statistics/Cargo.toml b/service-providers/network-statistics/Cargo.toml index e718333802..3c40a1ee53 100644 --- a/service-providers/network-statistics/Cargo.toml +++ b/service-providers/network-statistics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-network-statistics" -version = "1.1.28" +version = "1.1.29" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/internal/sdk-version-bump/Cargo.toml b/tools/internal/sdk-version-bump/Cargo.toml new file mode 100644 index 0000000000..07bb45a875 --- /dev/null +++ b/tools/internal/sdk-version-bump/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "sdk-version-bump" +version = "0.1.0" +authors.workspace = true +repository.workspace = true +homepage.workspace = true +documentation.workspace = true +edition.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = { workspace = true } +cargo-edit = "0.11.0" +clap = { version = "4.3.19", features = ["derive", "string"] } +semver = "1.0.18" +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } diff --git a/tools/internal/sdk-version-bump/README.md b/tools/internal/sdk-version-bump/README.md new file mode 100644 index 0000000000..0b161568be --- /dev/null +++ b/tools/internal/sdk-version-bump/README.md @@ -0,0 +1,19 @@ +# sdk-version-bump + +simple tool to update version numbers of our sdk packages. + +## Usage: + +note: this tool is expected to be run during CI, but if one wants to do it manually: + +### For releases: + +1. run `./sdk-version-bump remove-suffix` that will remove the `-rc.X` suffixes from all relevant packages +2. build everything and publish it to npm +3. run `./sdk-version-bump bump-version` that will update the versions of all relevant packages from `X.Y.Z` into `X.Y.(Z+1)-rc.0`. It will also update the `@nymproject/...` dependencies from `">=X.Y.Z-rc.0 || ^X"` to `">=X.Y.(Z+1)-rc.0 || ^X"` + +### For pre-releases: + +1. run `./sdk-version-bump bump-version --pre-release` that will update the release candidate version of all relevant packages from `X.Y.Z-rc.W` to `X.Y.Z-rc.(W+1)` + +To run it from the root, do: `cargo run -p sdk-version-bump` \ No newline at end of file diff --git a/tools/internal/sdk-version-bump/src/cargo.rs b/tools/internal/sdk-version-bump/src/cargo.rs new file mode 100644 index 0000000000..b00ab3889c --- /dev/null +++ b/tools/internal/sdk-version-bump/src/cargo.rs @@ -0,0 +1,47 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::ReleasePackage; +use anyhow::Context; +use cargo_edit::LocalManifest; +use semver::Version; +use std::path::Path; + +pub struct CargoPackage { + inner: LocalManifest, +} + +impl ReleasePackage for CargoPackage { + fn type_name() -> &'static str { + "Cargo.toml" + } + + fn open>(path: P) -> anyhow::Result { + let inner = LocalManifest::find(Some(path.as_ref()))?; + println!("\t>>> located the file at {}", inner.path.display()); + + Ok(CargoPackage { inner }) + } + + fn save_changes(&mut self) -> anyhow::Result<()> { + self.inner.write() + } + + fn get_current_version(&self) -> anyhow::Result { + self.inner + .manifest + .data + .get("package") + .context("no package")? + .get("version") + .context("no version")? + .as_str() + .context("not a valid str")? + .parse() + .map_err(Into::into) + } + + fn set_version(&mut self, version: &Version) { + self.inner.set_package_version(version); + } +} diff --git a/tools/internal/sdk-version-bump/src/helpers.rs b/tools/internal/sdk-version-bump/src/helpers.rs new file mode 100644 index 0000000000..455ea3487c --- /dev/null +++ b/tools/internal/sdk-version-bump/src/helpers.rs @@ -0,0 +1,164 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::{bail, Context}; +use semver::{Prerelease, Version}; +use std::collections::HashSet; +use std::path::Path; + +pub(crate) trait ReleasePackage: Sized { + fn type_name() -> &'static str; + + fn open>(path: P) -> anyhow::Result; + + fn save_changes(&mut self) -> anyhow::Result<()>; + + fn get_current_version(&self) -> anyhow::Result; + + fn set_version(&mut self, version: &Version); + + fn remove_suffix(&mut self) -> anyhow::Result<()> { + let version = self.get_current_version()?; + let updated = version.try_remove_prerelease()?; + + println!("\t>>> changing version from {version} to {updated}"); + self.set_version(&updated); + Ok(()) + } + + fn bump_version(&mut self, pre_release: bool) -> anyhow::Result<()> { + let version = self.get_current_version()?; + let updated = if pre_release { + version.try_bump_prerelease()? + } else { + version.try_bump_patch_without_pre()? + }; + + println!("\t>>> changing version from {version} to {updated}"); + self.set_version(&updated); + Ok(()) + } + + fn update_nym_dependencies(&mut self, _: &HashSet) -> anyhow::Result<()> { + Ok(()) + } +} + +pub(crate) trait VersionBumpExt: Sized { + fn try_bump_prerelease(&self) -> anyhow::Result; + fn try_bump_patch_without_pre(&self) -> anyhow::Result; + + fn set_initial_release_candidate(&self) -> anyhow::Result; + fn try_remove_prerelease(&self) -> anyhow::Result; +} + +impl VersionBumpExt for Version { + fn try_bump_prerelease(&self) -> anyhow::Result { + if self.pre.is_empty() { + bail!("the current version ({self}) does not have pre-release data set - are you sure you followed the release process correctly?") + } + + // ugh that's disgusting + let (rc_prefix, pre_version) = self + .pre + .as_str() + .split_once('.') + .context("the prerelease version does not contain a valid rc.X suffix")?; + + let parsed_version: u32 = pre_version.parse()?; + let updated_version = parsed_version + 1; + + let pre = format!("{rc_prefix}.{updated_version}").parse()?; + Ok(Version { + major: self.major, + minor: self.minor, + patch: self.patch, + pre, + build: self.build.clone(), + }) + } + + fn try_bump_patch_without_pre(&self) -> anyhow::Result { + if !self.pre.is_empty() { + bail!("the current version ({self}) has pre-release data set - are you sure you followed the release process correctly?") + } + + let mut updated = self.clone(); + updated.patch += 1; + Ok(updated) + } + + fn set_initial_release_candidate(&self) -> anyhow::Result { + if !self.pre.is_empty() { + bail!("the current version ({self}) has pre-release data set - are you sure you followed the release process correctly?") + } + Ok(Version { + major: self.major, + minor: self.minor, + patch: self.patch, + pre: Prerelease::new("rc.0")?, + build: self.build.clone(), + }) + } + + fn try_remove_prerelease(&self) -> anyhow::Result { + if self.pre.is_empty() { + bail!("the current version ({self}) does not have pre-release data set - are you sure you followed the release process correctly?") + } + Ok(Version { + major: self.major, + minor: self.minor, + patch: self.patch, + pre: Default::default(), + build: self.build.clone(), + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use semver::Version; + + #[test] + fn bump_patch_version() { + let cases = [ + ("1.0.0", Some("1.0.1")), + ("2.3.0", Some("2.3.1")), + ("1.0.0-rc.0", None), + ("1.0.0-rc.foomp", None), + ]; + + for (raw, expected) in cases { + let updated = Version::parse(raw).unwrap().try_bump_patch_without_pre(); + if let Some(expected) = expected { + let expected = Version::parse(expected).unwrap(); + assert_eq!(expected, updated.unwrap()) + } else { + assert!(updated.is_err()) + } + } + } + + #[test] + fn bump_rc_version() { + let cases = [ + ("1.0.0", None), + ("1.0.0-rc.0", Some("1.0.0-rc.1")), + ("1.0.0-rc.-1", None), + ("1.2.3-rc.42", Some("1.2.3-rc.43")), + ("1.2.3-rc42", None), + ("1.0.0-rc.foomp", None), + ]; + + for (raw, expected) in cases { + let updated = Version::parse(raw).unwrap().try_bump_prerelease(); + if let Some(expected) = expected { + let expected = Version::parse(expected).unwrap(); + assert_eq!(expected, updated.unwrap()) + } else { + assert!(updated.is_err()) + } + } + } +} diff --git a/tools/internal/sdk-version-bump/src/json.rs b/tools/internal/sdk-version-bump/src/json.rs new file mode 100644 index 0000000000..79b89e9d8d --- /dev/null +++ b/tools/internal/sdk-version-bump/src/json.rs @@ -0,0 +1,150 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::json_types::DepsSet; +use crate::{json_types, ReleasePackage}; +use anyhow::{bail, Context}; +use semver::{Comparator, Prerelease, Version, VersionReq}; +use std::collections::HashSet; +use std::path::{Path, PathBuf}; +use std::{env, fs}; + +pub struct PackageJson { + path: PathBuf, + inner: json_types::Package, +} + +fn update_dependencies(deps: &mut DepsSet, names: &HashSet) -> anyhow::Result<()> { + for (package, version) in deps.iter_mut() { + if names.contains(package) { + let updated = try_bump_minor_version_req(version)?; + + println!("\t\t>>> updating '{package}' from {version} to {updated}"); + *version = updated + } + } + Ok(()) +} + +impl ReleasePackage for PackageJson { + fn type_name() -> &'static str { + "package.json" + } + + fn open>(path: P) -> anyhow::Result { + let path = find(Some(path.as_ref()))?; + println!("\t>>> located the file at {}", path.display()); + + let inner = json_types::Package::from_path(&path)?; + Ok(PackageJson { path, inner }) + } + + fn save_changes(&mut self) -> anyhow::Result<()> { + let file = std::fs::File::create(&self.path)?; + Ok(serde_json::to_writer_pretty(file, &self.inner)?) + } + + fn get_current_version(&self) -> anyhow::Result { + self.inner.version.parse().map_err(Into::into) + } + + fn set_version(&mut self, version: &Version) { + self.inner.version = version.to_string() + } + + fn update_nym_dependencies(&mut self, names: &HashSet) -> anyhow::Result<()> { + println!("\t>>> updating @nymproject dependencies..."); + update_dependencies(&mut self.inner.dependencies, names)?; + + println!("\t>>> updating @nymproject peerDependencies..."); + update_dependencies(&mut self.inner.peer_dependencies, names)?; + + println!("\t>>> updating @nymproject devDependencies..."); + update_dependencies(&mut self.inner.dev_dependencies, names)?; + + println!("\t>>> updating @nymproject optionalDependencies..."); + update_dependencies(&mut self.inner.optional_dependencies, names)?; + + println!("\t>>> updating @nymproject bundledDependencies..."); + update_dependencies(&mut self.inner.bundled_dependencies, names)?; + + Ok(()) + } +} + +pub fn find(specified: Option<&Path>) -> anyhow::Result { + match specified { + Some(path) + if fs::metadata(path) + .with_context(|| "Failed to get cargo file metadata")? + .is_file() => + { + Ok(path.to_owned()) + } + Some(path) => find_package_path(path), + None => find_package_path( + &env::current_dir().with_context(|| "Failed to get current directory")?, + ), + } +} + +pub(crate) fn find_package_path(dir: &Path) -> anyhow::Result { + const MANIFEST_FILENAME: &str = "package.json"; + for path in dir.ancestors() { + let manifest = path.join(MANIFEST_FILENAME); + if std::fs::metadata(&manifest).is_ok() { + return Ok(manifest); + } + } + anyhow::bail!("Unable to find package.json for {}", dir.display()); +} + +// expected structure: `>=X.Y.Z-rc.W || ^X` +fn try_bump_minor_version_req(raw_req: &str) -> anyhow::Result { + let (req, major) = raw_req + .split_once("||") + .context("invalid version requirement")?; + let parsed_req = VersionReq::parse(req)?; + let parsed_major = VersionReq::parse(major)?; + if parsed_req.comparators.len() != 1 { + bail!("wrong number of version requirements present in {parsed_req}") + } + + let updated = VersionReq { + comparators: vec![Comparator { + op: parsed_req.comparators[0].op, + major: parsed_req.comparators[0].major, + minor: parsed_req.comparators[0].minor, + patch: parsed_req.comparators[0].patch.map(|p| p + 1), + pre: Prerelease::new("rc.0")?, + }], + }; + + Ok(format!("{updated} || {parsed_major}")) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn bumping_version_req() { + let cases = [ + (">=1.2.0-rc.0 || ^1", Some(">=1.2.1-rc.0 || ^1")), + (">=1.2.0-rc.0 || 1", Some(">=1.2.1-rc.0 || ^1")), + (">=1.2.0-rc.5 || ^1", Some(">=1.2.1-rc.0 || ^1")), + (">=1.2.0-rc.5 || 1", Some(">=1.2.1-rc.0 || ^1")), + (">=1.2.0-rc.0", None), + ("1.0.0-rc.0", None), + ]; + + for (raw, expected) in cases { + let updated = try_bump_minor_version_req(raw); + if let Some(expected) = expected { + assert_eq!(expected, updated.unwrap()) + } else { + assert!(updated.is_err()) + } + } + } +} diff --git a/tools/internal/sdk-version-bump/src/json_types.rs b/tools/internal/sdk-version-bump/src/json_types.rs new file mode 100644 index 0000000000..c1fe612685 --- /dev/null +++ b/tools/internal/sdk-version-bump/src/json_types.rs @@ -0,0 +1,281 @@ +// source: https://crates.io/crates/npm-package-json + +//! `serde` mappings for npm's `package.json` file format. +//! +//! This does only implement the fields defined [in the official npm documentation](https://docs.npmjs.com/files/package.json). +//! It is common enough that packages define custom entries that are required by +//! various tooling. + +#![warn( + missing_copy_implementations, + missing_debug_implementations, + missing_docs, + unsafe_code +)] + +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::{collections::BTreeMap, fmt, fs, io::Read, path::Path, str::FromStr}; + +/// An ordered map for `bin` entries. +pub type BinSet = BTreeMap; +/// An ordered map for `dependencies` entries. +pub type DepsSet = BTreeMap; +/// An ordered map for `engines` entries. +pub type EnginesSet = BTreeMap; +/// An ordered map for `scripts` entries. +pub type ScriptsSet = BTreeMap; + +/// A bug contacting form. +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +pub struct Bug { + /// The email to use for contact. + #[serde(skip_serializing_if = "Option::is_none")] + pub email: Option, + /// The url to use to submit bugs. + #[serde(skip_serializing_if = "Option::is_none")] + pub url: Option, +} + +impl Bug { + /// Creates a new default bug. + pub fn new() -> Self { + Self::default() + } + + /// Creates a new bug with the given values. + pub fn with(email: Option, url: Option) -> Self { + Self { email, url } + } +} + +/// A person. +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +pub struct Person { + /// The name of a person. + pub name: String, + /// The email of a person. + #[serde(skip_serializing_if = "Option::is_none")] + pub email: Option, + /// The homepage of the person. + #[serde(skip_serializing_if = "Option::is_none")] + pub url: Option, +} + +impl Person { + /// Creates a default person. + pub fn new() -> Self { + Self::default() + } + + /// Creates a person with a given name. + pub fn with_name(name: String) -> Self { + Self { + name, + ..Default::default() + } + } + + /// Creates a person with the given values. + pub fn with(name: String, email: Option, url: Option) -> Self { + Self { name, email, url } + } +} + +impl fmt::Display for Person { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match (&self.name, self.email.as_ref(), self.url.as_ref()) { + (name, Some(email), None) => write!(f, "{} <{}>", name, email), + (name, None, Some(url)) => write!(f, "{} ({})", name, url), + (name, None, None) => write!(f, "{}", name), + (name, Some(email), Some(url)) => write!(f, "{} <{}> ({})", name, email, url), + } + } +} + +/// A reference to a person. +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(untagged)] +pub enum PersonReference { + /// A short reference. + /// + /// Short references have a fixed format of `John Doe (https://john.doe.dev)`. + Short(String), + /// A full reference. + /// + /// This type of reference defines the parts using a struct instead of a + /// shorthand string format. + Full(Person), +} + +/// A reference to a man page. +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(untagged)] +pub enum ManReference { + /// A single man page reference. Points to one single file. + Single(String), + /// Multiple man pages, can contain anything from zero to n. + Multiple(Vec), +} + +/// A repository. +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +pub struct Repository { + /// The version control system that the repository uses. + pub r#type: String, + /// The url to the repository. + pub url: String, + /// The directory that the repository is in. Often used for monorepos. + #[serde(skip_serializing_if = "Option::is_none")] + pub directory: Option, +} + +/// A repository reference. +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(untagged)] +pub enum RepositoryReference { + /// A short reference to the repository. Has to have the syntax that `npm install` allows as well. For more information see [here](https://docs.npmjs.com/files/package.json#repository). + Short(String), + /// A full reference. + Full(Repository), +} + +/// The top-level `package.json` structure. +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct Package { + /// The package name. + pub name: String, + /// The package version. + pub version: String, + /// The optional package description. + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + /// The optional list of keywords. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub keywords: Vec, + /// The optional package homepage. + #[serde(skip_serializing_if = "Option::is_none")] + pub homepage: Option, + /// The optional bug contact form. + #[serde(skip_serializing_if = "Option::is_none")] + pub bugs: Option, + /// The optional package license. + #[serde(skip_serializing_if = "Option::is_none")] + pub license: Option, + /// The optional author. + #[serde(skip_serializing_if = "Option::is_none")] + pub author: Option, + /// The optional list of contributors. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub contributors: Vec, + /// The optional list of files to include. Each entry defines a regex + /// pattern. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub files: Vec, + /// The optional package main entry file. + #[serde(skip_serializing_if = "Option::is_none")] + pub main: Option, + /// The optional package browser entry file. + /// + /// This is usually defined in libraries that are meant to be consumed by + /// browsers. These Thoes can refer to objects that are not available inside + /// a `nodejs` environment (like `window`). + #[serde(skip_serializing_if = "Option::is_none")] + pub browser: Option, + /// The optional set of binary definitions. + #[serde(default, skip_serializing_if = "BinSet::is_empty")] + pub bin: BinSet, + /// The optional list of man page references. + #[serde(skip_serializing_if = "Option::is_none")] + pub man: Option, + /// The optional repository reference. + //#[serde(flatten)] + #[serde(skip_serializing_if = "Option::is_none")] + pub repository: Option, + /// The optional list of script entries. + #[serde(default, skip_serializing_if = "ScriptsSet::is_empty")] + pub scripts: ScriptsSet, + /// The optional list of dependencies. + #[serde(default, skip_serializing_if = "DepsSet::is_empty")] + pub dependencies: DepsSet, + /// The optional list of development dependencies. + #[serde(default, skip_serializing_if = "DepsSet::is_empty")] + pub dev_dependencies: DepsSet, + /// The optional list of peer dependencies. + #[serde(default, skip_serializing_if = "DepsSet::is_empty")] + pub peer_dependencies: DepsSet, + /// The optional list of bundled dependencies. + #[serde(default, skip_serializing_if = "DepsSet::is_empty")] + pub bundled_dependencies: DepsSet, + /// The optional list of optional dependencies. + #[serde(default, skip_serializing_if = "DepsSet::is_empty")] + pub optional_dependencies: DepsSet, + /// The optional list of engine entries. + #[serde(default, skip_serializing_if = "EnginesSet::is_empty")] + pub engines: EnginesSet, + /// The package privacy. + #[serde(default)] + pub private: bool, + /// The OS' that the package can run on. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub os: Vec, + /// The CPU architectures that the package can run on. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub cpu: Vec, + /// The optional config object. + #[serde(skip_serializing_if = "Option::is_none")] + pub config: Option, + /// Other custom fields that have been defined inside the `package.json` + /// file. + #[serde(flatten)] + pub others: BTreeMap, +} + +impl Package { + /// Creates a new default package. + pub fn new() -> Self { + Self::default() + } + + /// Deserializes a `Package` from a file path. + pub fn from_path(path: impl AsRef) -> anyhow::Result { + let content = fs::read(path.as_ref())?; + Self::from_slice(content.as_slice()) + } + + /// Deserializes a `Package` from an IO stream. + pub fn from_reader(r: R) -> anyhow::Result { + Ok(serde_json::from_reader(r)?) + } + + /// Deserializes a `Package` from bytes. + pub fn from_slice(v: &[u8]) -> anyhow::Result { + Ok(serde_json::from_slice(v)?) + } +} + +impl FromStr for Package { + type Err = anyhow::Error; + + /// Deserializes a `Package` from a string. + fn from_str(s: &str) -> Result { + Ok(serde_json::from_str(s)?) + } +} + +#[cfg(test)] +mod tests { + use super::Person; + + #[test] + fn test_person_display() { + let person = Person { + name: "John Doe".to_string(), + email: Some("john@doe.dev".to_string()), + url: Some("https://john.doe.dev".to_string()), + }; + let expected = "John Doe (https://john.doe.dev)"; + assert_eq!(expected, person.to_string()); + } +} diff --git a/tools/internal/sdk-version-bump/src/main.rs b/tools/internal/sdk-version-bump/src/main.rs new file mode 100644 index 0000000000..fe827b54a8 --- /dev/null +++ b/tools/internal/sdk-version-bump/src/main.rs @@ -0,0 +1,208 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cargo::CargoPackage; +use crate::helpers::ReleasePackage; +use crate::json::PackageJson; +use clap::{Parser, Subcommand}; +use std::collections::HashSet; +use std::env; +use std::path::{Path, PathBuf}; + +mod cargo; +mod helpers; +mod json; +pub mod json_types; + +fn default_root() -> PathBuf { + env::current_dir().unwrap() +} + +#[derive(Parser)] +struct Args { + #[arg(default_value=default_root().into_os_string())] + root: PathBuf, + + #[clap(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + /// Will strip any `-rc.X` suffixes from the package versions + RemoveSuffix, + + /// Will update the versions of all relevant packages from `X.Y.Z` into `X.Y.(Z+1)-rc.0`. + /// It will also update the `@nymproject/...` dependencies from `">=X.Y.Z-rc.0 || ^X"` to `">=X.Y.(Z+1)-rc.0 || ^X"` + BumpVersion { + #[arg(long)] + /// If enabled, the packages will only have their rc version bumped and the dependencies won't get updated at all + pre_release: bool, + }, +} + +fn remove_suffix(root: &Path, path: impl AsRef) { + let path = root.join(path); + println!( + ">>> [{}] UPDATING PACKAGE {}: ", + Pkg::type_name(), + path.display() + ); + + if let Err(err) = { remove_suffix_inner::(path) } { + println!("\t>>> ❌ FAILURE: {err}"); + } else { + println!("\t>>> ✅ SUCCESS"); + } +} + +fn remove_suffix_inner(path: impl AsRef) -> anyhow::Result<()> { + println!("\t>>> opening the package file..."); + let mut package = Pkg::open(path)?; + package.remove_suffix()?; + + println!("\t>>> saving the package file..."); + package.save_changes() +} + +fn bump_version( + root: &Path, + path: impl AsRef, + dependencies_to_update: &HashSet, + pre_release: bool, +) { + let path = root.join(path); + println!( + ">>> [{}] UPDATING PACKAGE {}: ", + Pkg::type_name(), + path.display() + ); + if let Err(err) = { bump_version_inner::(path, dependencies_to_update, pre_release) } { + println!("\t>>> ❌ FAILURE: {err}"); + } else { + println!("\t>>> ✅ SUCCESS"); + } +} + +fn bump_version_inner( + path: impl AsRef, + dependencies_to_update: &HashSet, + pre_release: bool, +) -> anyhow::Result<()> { + println!("\t>>> opening the package file..."); + let mut package = Pkg::open(path)?; + package.bump_version(pre_release)?; + + if !pre_release { + package.update_nym_dependencies(dependencies_to_update)?; + } + + println!("\t>>> saving the package file..."); + package.save_changes() +} + +#[derive(Default)] +struct InternalPackages { + root: PathBuf, + cargo: HashSet, + json: HashSet, + + internal_js_dependencies: HashSet, +} + +impl InternalPackages { + pub fn new>(root: P) -> Self { + InternalPackages { + root: root.as_ref().to_path_buf(), + cargo: Default::default(), + json: Default::default(), + internal_js_dependencies: Default::default(), + } + } + + pub fn register_cargo>(&mut self, relative_path: S) { + self.cargo.insert(relative_path.into()); + } + + pub fn register_json>(&mut self, relative_path: S) { + self.json.insert(relative_path.into()); + } + + pub fn register_known_js_dependency>(&mut self, name: S) { + self.internal_js_dependencies.insert(name.into()); + } + + pub fn remove_suffix(&self) { + for cargo_package in &self.cargo { + remove_suffix::(&self.root, cargo_package); + } + + for package_json in &self.json { + remove_suffix::(&self.root, package_json); + } + } + + pub fn bump_version(&self, pre_release: bool) { + for cargo_package in &self.cargo { + bump_version::( + &self.root, + cargo_package, + &Default::default(), + pre_release, + ); + } + + for package_json in &self.json { + bump_version::( + &self.root, + package_json, + &self.internal_js_dependencies, + pre_release, + ); + } + } +} + +fn initialise_internal_packages>(root: P) -> InternalPackages { + let mut packages = InternalPackages::new(root); + + // cargo packages that will have their Cargo.toml modified + packages.register_cargo("wasm/mix-fetch"); + packages.register_cargo("wasm/client"); + packages.register_cargo("wasm/node-tester"); + packages.register_cargo("wasm/full-nym-wasm"); + packages.register_cargo("nym-browser-extension/storage"); + + // js packages that will have their package.json modified + packages.register_json("sdk/typescript/packages/mix-fetch"); + packages.register_json("sdk/typescript/packages/mui-theme"); + packages.register_json("sdk/typescript/packages/node-tester"); + packages.register_json("sdk/typescript/packages/react-components"); + packages.register_json("sdk/typescript/packages/sdk"); + packages.register_json("sdk/typescript/packages/sdk-react"); + packages.register_json("sdk/typescript/packages/validator-client"); + + // dependencies that will have their versions adjusted in the above packages + packages.register_known_js_dependency("@nymproject/mix-fetch"); + packages.register_known_js_dependency("@nymproject/mui-theme"); + packages.register_known_js_dependency("@nymproject/node-tester"); + packages.register_known_js_dependency("@nymproject/react-components"); + packages.register_known_js_dependency("@nymproject/sdk"); + packages.register_known_js_dependency("@nymproject/sdk-react"); + packages.register_known_js_dependency("@nymproject/react"); + packages.register_known_js_dependency("@nymproject/nym-validator-client"); + + packages +} + +fn main() -> anyhow::Result<()> { + let args = Args::parse(); + let packages = initialise_internal_packages(args.root); + + match args.command { + Commands::RemoveSuffix => packages.remove_suffix(), + Commands::BumpVersion { pre_release } => packages.bump_version(pre_release), + } + + Ok(()) +} diff --git a/tools/internal/ssl-inject/Cargo.toml b/tools/internal/ssl-inject/Cargo.toml new file mode 100644 index 0000000000..41d42fc496 --- /dev/null +++ b/tools/internal/ssl-inject/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "ssl-inject" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +tokio = { version = "*", features = ["full"]} +anyhow = "1.0.71" +hex = "0.4.3" +clap = { version = "4.0", features = ["derive"] } diff --git a/tools/internal/ssl-inject/src/main.rs b/tools/internal/ssl-inject/src/main.rs new file mode 100644 index 0000000000..153bd372e2 --- /dev/null +++ b/tools/internal/ssl-inject/src/main.rs @@ -0,0 +1,96 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use std::io; +use std::time::Duration; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::TcpStream; +use tokio::select; +use tokio::time::sleep; + +#[derive(Parser)] +struct Args { + // ipv4 nymtech.net address + #[clap(long, default_value = "185.19.28.43:443")] + target: String, +} + +fn decode_hex(raw: &str) -> Vec { + hex::decode(raw).unwrap() +} + +fn encode_hex(bytes: &[u8]) -> String { + hex::encode(bytes) +} + +fn read_line() -> anyhow::Result { + let mut buffer = String::new(); + io::stdin().read_line(&mut buffer)?; + Ok(buffer) +} + +async fn read_from_conn(conn: &mut TcpStream) -> Vec { + let timeout = sleep(Duration::from_secs(1)); + tokio::pin!(timeout); + + let mut read = Vec::new(); + loop { + let mut buf = [0u8; 1024]; + select! { + _ = &mut timeout => { + return read + } + res = conn.read(&mut buf) => { + let n = res.unwrap(); + if n == 0 { + return read + } + println!("read {n} bytes"); + read.append(&mut buf[..n].to_vec()) + } + + } + } +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let args = Args::parse(); + let target = args.target; + + println!("connecting to {target}"); + let mut conn = TcpStream::connect(target).await?; + println!("connected"); + + loop { + println!("[Client] >>> "); + let client_hello = read_line()?; + let raw = decode_hex(client_hello.trim()); + conn.write_all(&raw).await?; + + let data = read_from_conn(&mut conn).await; + let encoded = encode_hex(&data); + println!("[Server] >>>\n{encoded}"); + } + + // println!("[ClientHello] >>> "); + // let client_hello = read_line()?; + // let raw = decode_hex(client_hello.trim()); + // conn.write_all(&raw).await?; + // + // let data = read_from_conn(&mut conn).await; + // let encoded = encode_hex(&data); + // println!("[ServerHello] >>>\n{encoded}"); + // + // println!("[ClientKeyExchange] >>> "); + // let client_response = read_line()?; + // let raw = decode_hex(client_response.trim()); + // conn.write_all(&raw).await?; + // + // let data = read_from_conn(&mut conn).await; + // let encoded = encode_hex(&data); + // println!("[ServerFinished] >>>\n{encoded}"); + + // Ok(()) +} diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml index 455da72803..deaa5dd10b 100644 --- a/tools/nym-cli/Cargo.toml +++ b/tools/nym-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-cli" -version = "1.1.28" +version = "1.1.29" authors.workspace = true edition = "2021" diff --git a/ts-packages/react-webpack-with-theme-example/.babelrc b/ts-packages/react-webpack-with-theme-example/.babelrc deleted file mode 100644 index 85e1f1ba26..0000000000 --- a/ts-packages/react-webpack-with-theme-example/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@babel/env", "@babel/react"] -} \ No newline at end of file diff --git a/ts-packages/react-webpack-with-theme-example/jest.config.js b/ts-packages/react-webpack-with-theme-example/jest.config.js deleted file mode 100644 index e86e13bab9..0000000000 --- a/ts-packages/react-webpack-with-theme-example/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', -}; diff --git a/wasm/client/.cargo/config.toml b/wasm/client/.cargo/config.toml new file mode 100644 index 0000000000..a7f24f6737 --- /dev/null +++ b/wasm/client/.cargo/config.toml @@ -0,0 +1,6 @@ +[build] +target = "wasm32-unknown-unknown" +target_arch = "wasm32" + +[target.wasm32-unknown-unknown] +runner = 'wasm-bindgen-test-runner' \ No newline at end of file diff --git a/wasm/client/Cargo.toml b/wasm/client/Cargo.toml new file mode 100644 index 0000000000..1642f95ec1 --- /dev/null +++ b/wasm/client/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "nym-client-wasm" +authors = ["Dave Hrycyszyn ", "Jedrzej Stuczynski "] +version = "1.2.0-rc.2" +edition = "2021" +keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy", "client"] +license = "Apache-2.0" +repository = "https://github.com/nymtech/nym" +description = "A webassembly client which can be used to interact with the the Nym privacy platform. Wasm is used for Sphinx packet generation." +rust-version = "1.56" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +anyhow = "1.0" +futures = { workspace = true } +js-sys = { workspace = true } +rand = { version = "0.7.3", features = ["wasm-bindgen"] } +serde = { workspace = true, features = ["derive"] } +serde_json = "1.0" +serde-wasm-bindgen = { workspace = true } +wasm-bindgen = { workspace = true } +wasm-bindgen-futures = { workspace = true } +thiserror = { workspace = true } +tsify = { workspace = true, features = ["js"] } + +wasm-client-core = { path = "../../common/wasm/client-core" } +wasm-utils = { path = "../../common/wasm/utils" } + +nym-node-tester-utils = { path = "../../common/node-tester-utils", optional = true } +nym-node-tester-wasm = { path = "../node-tester", optional = true} + +[dev-dependencies] +wasm-bindgen-test = "0.3.36" + +[features] +default = ["node-tester"] +node-tester = ["nym-node-tester-wasm", "nym-node-tester-utils"] + +[package.metadata.wasm-pack.profile.release] +wasm-opt = false + +[profile.release] +lto = true +opt-level = 'z' diff --git a/wasm/client/Makefile b/wasm/client/Makefile new file mode 100644 index 0000000000..43a0cf5940 --- /dev/null +++ b/wasm/client/Makefile @@ -0,0 +1,7 @@ +build: + wasm-pack build --scope nymproject --target web --out-dir ../../dist/wasm/client + wasm-opt -Oz -o ../../dist/wasm/client/nym_client_wasm_bg.wasm ../../dist/wasm/client/nym_client_wasm_bg.wasm + +build-node: + wasm-pack build --scope nymproject --target nodejs --out-dir ../../dist/node/wasm/client + wasm-opt -Oz -o ../../dist/node/wasm/client/nym_client_wasm_bg.wasm ../../dist/node/wasm/client/nym_client_wasm_bg.wasm \ No newline at end of file diff --git a/clients/webassembly/README.md b/wasm/client/README.md similarity index 62% rename from clients/webassembly/README.md rename to wasm/client/README.md index 6f290c1506..6d4bccd319 100644 --- a/clients/webassembly/README.md +++ b/wasm/client/README.md @@ -20,18 +20,20 @@ See the [SDK directory](../../sdk/typescript/examples) for examples on how to us ## Developing -This is a Rust crate which is set up to automatically cross-compile the contents of `src` to WebAssembly (aka wasm). It's published from the main [Nym platform monorepo](https://github.com/nymtech/nym) in the `clients/webassembly` directory. +Make sure you have `wasm-pack` installed (`cargo install wasm-pack`) before you start. -First, make sure you've got all the [Rust wasm toolchain](https://rustwasm.github.io/docs/book/) installed. Cross-compilation sounds scary, but the Rust crew have enabled a remarkably simple setup. +Please use the [Makefile](Makefile) targets to build this crate and compile it to WASM: -Furthermore, [wasm-bindgen documentation](https://rustwasm.github.io/docs/wasm-bindgen/) provides excellent tips to solving common problems. +``` +make build +``` -Whenever you change any Rust in the `src` directory, run `wasm-pack build --scope nymproject` to update the built wasm artefact in the `pkg` directory. - -To be clear, this is not something that most JS developers need to worry about, this is only for Nym devs. The packages on NPM have all files in place. Just install and enjoy! +The outputs will be found [here](../../dist/wasm/client) where it will be accessible to the rest of the monorepo using workspaces. ### Packaging +> **TODO** + If you're a Nym platform developer who's made changes to the Rust files and wants to re-publish the package to NPM, here's how you do it: 1. bump version numbers as necessary for SemVer diff --git a/wasm/client/internal-dev-node/.gitignore b/wasm/client/internal-dev-node/.gitignore new file mode 100644 index 0000000000..6a91a439ea --- /dev/null +++ b/wasm/client/internal-dev-node/.gitignore @@ -0,0 +1 @@ +*.sqlite \ No newline at end of file diff --git a/wasm/client/internal-dev-node/package.json b/wasm/client/internal-dev-node/package.json new file mode 100644 index 0000000000..e845361914 --- /dev/null +++ b/wasm/client/internal-dev-node/package.json @@ -0,0 +1,16 @@ +{ + "name": "internal-dev-node", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "node src/index.mjs" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@nymproject/nym-client-wasm": "file:../../../dist/node/wasm/client", + "indexeddbshim": "^13.0.0-pre.1", + "ws": "^8.13.0" + } +} diff --git a/wasm/client/internal-dev-node/src/index.mjs b/wasm/client/internal-dev-node/src/index.mjs new file mode 100644 index 0000000000..b9c5bfbe47 --- /dev/null +++ b/wasm/client/internal-dev-node/src/index.mjs @@ -0,0 +1,105 @@ +import {Worker} from 'worker_threads'; + +function sleep(ms) { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +} + +class NodeWorkerClient { + worker = null; + clientInitialised = false; + selfAddress = null + + constructor() { + this.worker = new Worker('./src/worker.mjs'); + + this.worker.on("message", message => { + this.handleMessage(message) + }); + + this.worker.on("error", error => { + console.log(error); + }); + + this.worker.on("exit", exitCode => { + console.log(`It exited with code ${exitCode}`); + }) + + } + + initWasmClient = () => { + this.worker.postMessage({kind: 'initRequest', data: {}}) + } + + sendMessage = (message, recipient) => { + this.worker.postMessage({kind: 'sendRequest', data: {message, recipient}}) + } + + handleReceived = (message, senderTag) => { + console.log(`received raw message: ${message}`) + console.log(`with senderTag: ${senderTag}`) + + let decoded = new TextDecoder().decode(message); + console.log(`decoded message: "${decoded}"`) + } + + handleMessage = (message) => { + console.log(`handling "${message.kind}"`) + switch (message.kind) { + case 'initResponse': + this.clientInitialised = message.data.done; + this.selfAddress = message.data.clientAddress + break; + case 'receivedMessage': + this.handleReceived(message.data.message, message.data.senderTag) + break; + default: + console.log("UNKOWN MESSAGE") + break; + } + } + + // hehe, that's so disgusting, but I don't want to spend ages in the JS callback hell + // because that's not the point of this example + waitForWasmClient = async () => { + let start = new Date(); + let pollingRate = 100; + let maxWaitSecs = 5; + while (!this.clientInitialised) { + let now = new Date(); + let diff = (now.getTime() - start.getTime()) / 1000; + if (diff > maxWaitSecs) { + return Promise.reject(new Error('failed to initialise wasm client')) + } + await sleep(pollingRate) + } + } +} + + +async function main() { + let client = new NodeWorkerClient() + client.initWasmClient() + await client.waitForWasmClient() + + let ourAddress = client.selfAddress + console.log("main thread address: ", ourAddress) + + let message = "hello world" + let uint8Array = new TextEncoder().encode(message); + console.log(`sending "${message}" to ourselves...`) + client.sendMessage(uint8Array, ourAddress) +} + +await main() + +process.on('SIGTERM', signal => { + console.log(`Process ${process.pid} received a SIGTERM signal`) + process.exit(0) +}) + +process.on('SIGINT', signal => { + console.log(`Process ${process.pid} has been interrupted`) + process.exit(0) +}) \ No newline at end of file diff --git a/wasm/client/internal-dev-node/src/worker.mjs b/wasm/client/internal-dev-node/src/worker.mjs new file mode 100644 index 0000000000..d4afd1396a --- /dev/null +++ b/wasm/client/internal-dev-node/src/worker.mjs @@ -0,0 +1,88 @@ +import {parentPort} from 'worker_threads'; +import setGlobalVars from 'indexeddbshim'; +import WebSocket from 'ws'; +import {NymClient, set_panic_hook} from '@nymproject/nym-client-wasm'; + +// polyfill setup +const globalVar = + typeof window !== "undefined" + ? window + : typeof WorkerGlobalScope !== "undefined" + ? self + : typeof global !== "undefined" + ? global + : Function("return this;")(); + +// checkOrigin:false is required to avoid SecurityError Cannot open +// an IndexedDB database from an opaque origin. +setGlobalVars(globalVar, {checkOrigin: false}) +globalVar.WebSocket = WebSocket + +let initDone = false +let nymClient = null +let clientAddress = null + +parentPort.on('message', async message => { + await handleMessage(message) +}); + +function onReceived(message, senderTag) { + parentPort.postMessage({kind: 'receivedMessage', data: {message, senderTag}}); +} + +async function handleMessage(message) { + console.log(`handling "${message.kind}"`) + switch (message.kind) { + case 'initRequest': + await initialiseWasmClient() + break; + case 'sendRequest': + await handleSendRequest(message.data.message, message.data.recipient); + break; + default: + console.log("UNKOWN MESSAGE") + break; + } +} + +async function handleSendRequest(message, recipient) { + await nymClient.send_regular_message(message, recipient) +} + +async function nativeSetup(onMessageHandler) { + const validator = 'https://validator.nymtech.net/api/'; + + const noCoverTrafficOverride = { + traffic: {disableMainPoissonPacketDistribution: true}, + coverTraffic: {disableLoopCoverTrafficStream: true}, + } + + return new NymClient(onMessageHandler, { + storagePassphrase: "foomp", + nymApiUrl: validator, + clientId: "my-client", + clientOverride: noCoverTrafficOverride + }) +} + + +function finishInit() { + initDone = true + parentPort.postMessage({kind: 'initResponse', data: {done: initDone, clientAddress}}) +} + +async function initialiseWasmClient() { + if (initDone) { + return finishInit() + } + + // sets up better stack traces in case of in-rust panics + set_panic_hook(); + + console.log('Instantiating WASM client...'); + nymClient = await nativeSetup(onReceived) + clientAddress = nymClient.self_address() + console.log('WASM client running!'); + + finishInit() +} diff --git a/wasm/client/internal-dev-node/yarn.lock b/wasm/client/internal-dev-node/yarn.lock new file mode 100644 index 0000000000..3932b9c4b2 --- /dev/null +++ b/wasm/client/internal-dev-node/yarn.lock @@ -0,0 +1,899 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@gar/promisify@^1.0.1": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" + integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== + +"@mapbox/node-pre-gyp@^1.0.0": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" + integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ== + dependencies: + detect-libc "^2.0.0" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.7" + nopt "^5.0.0" + npmlog "^5.0.1" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.11" + +"@npmcli/fs@^1.0.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" + integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== + dependencies: + "@gar/promisify" "^1.0.1" + semver "^7.3.5" + +"@npmcli/move-file@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" + integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== + dependencies: + mkdirp "^1.0.4" + rimraf "^3.0.2" + +"@nymproject/nym-client-wasm@file:../../../dist/node/wasm/client": + version "1.2.0-rc.2" + +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +agent-base@6, agent-base@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +agentkeepalive@^4.1.3: + version "4.5.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" + integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== + dependencies: + humanize-ms "^1.2.1" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +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== + +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +are-we-there-yet@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" + integrity sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +argsarray@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/argsarray/-/argsarray-0.0.1.tgz#6e7207b4ecdb39b0af88303fa5ae22bda8df61cb" + integrity sha512-u96dg2GcAKtpTrBdDoFIM7PjcBA+6rSP0OR94MOReNRyUECL6MtQt5XXmRr4qrftYaef9+l5hcpO5te7sML1Cg== + +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== + +base64-arraybuffer-es6@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/base64-arraybuffer-es6/-/base64-arraybuffer-es6-3.0.1.tgz#2ad032cc4e378de6bbd7aa1b29f695b277dc4474" + integrity sha512-bOxevePlYA8Kba1xVnrQSoktrt12UkP6Jhl2wO+GCGbKAkF4fpDxyg7xRFffZYC0kP2RgMPOSRbzmdHReWnMyg== + +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" + +cacache@^15.2.0: + version "15.3.0" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" + integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== + dependencies: + "@npmcli/fs" "^1.0.0" + "@npmcli/move-file" "^1.0.1" + chownr "^2.0.0" + fs-minipass "^2.0.0" + glob "^7.1.4" + infer-owner "^1.0.4" + lru-cache "^6.0.0" + minipass "^3.1.1" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^1.0.3" + p-map "^4.0.0" + promise-inflight "^1.0.1" + rimraf "^3.0.2" + ssri "^8.0.1" + tar "^6.0.2" + unique-filename "^1.1.1" + +canvas@^2.11.2: + version "2.11.2" + resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.11.2.tgz#553d87b1e0228c7ac0fc72887c3adbac4abbd860" + integrity sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.0" + nan "^2.17.0" + simple-get "^3.0.3" + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +color-support@^1.1.2, color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +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== + +console-control-strings@^1.0.0, console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + +debug@4, debug@^4.3.3: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +detect-libc@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.2.tgz#8ccf2ba9315350e1241b88d0ac3b0e1fbd99605d" + integrity sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw== + +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== + +encoding@^0.1.12: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +err-code@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" + integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== + +eventtargeter@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/eventtargeter/-/eventtargeter-0.9.0.tgz#2c8b873dce173a831779e5f9f5a07facda61e7cd" + integrity sha512-40f2UpTpS7v2GnXWsMpEUkKoMOlgTDrijhCx4Hq7zvsBhLihA7dn0Ayicb4FO/MOIzD5mLHsLK7/NYqx39LqaA== + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.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== + +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + +gauge@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" + integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.3" + console-control-strings "^1.1.0" + has-unicode "^2.0.1" + signal-exit "^3.0.7" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.5" + +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" + +graceful-fs@^4.2.6: + 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-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + +http-cache-semantics@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== + dependencies: + ms "^2.0.0" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +immediate@^3.2.2: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +indexeddbshim@^13.0.0-pre.1: + version "13.0.0-pre.1" + resolved "https://registry.yarnpkg.com/indexeddbshim/-/indexeddbshim-13.0.0-pre.1.tgz#445a1ee71f57f6d8b20ada214e197b3e2a55582b" + integrity sha512-Tl0FAiQvp0zdTiWZf267d6MN0cFk64z8oa39zpexIkX3Nk/AY5iYhPqvpQcGOxXJWdY/IWOyZFZb4K2qhRtxng== + dependencies: + canvas "^2.11.2" + eventtargeter "0.9.0" + sync-promise-expanded "^1.0.0" + typeson "9.0.2" + typeson-registry "7.2.1" + websql-configurable "^3.0.3" + +infer-owner@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + +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, inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ip@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" + integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== + +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-lambda@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" + integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-fetch-happen@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" + integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== + dependencies: + agentkeepalive "^4.1.3" + cacache "^15.2.0" + http-cache-semantics "^4.1.0" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-lambda "^1.0.1" + lru-cache "^6.0.0" + minipass "^3.1.3" + minipass-collect "^1.0.2" + minipass-fetch "^1.3.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.2" + promise-retry "^2.0.1" + socks-proxy-agent "^6.0.0" + ssri "^8.0.0" + +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + +minimatch@^3.1.1: + 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" + +minipass-collect@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" + integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== + dependencies: + minipass "^3.0.0" + +minipass-fetch@^1.3.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6" + integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw== + dependencies: + minipass "^3.1.0" + minipass-sized "^1.0.3" + minizlib "^2.0.0" + optionalDependencies: + encoding "^0.1.12" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== + dependencies: + minipass "^3.0.0" + +minipass-sized@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" + integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== + dependencies: + minipass "^3.0.0" + +minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +minizlib@^2.0.0, minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^1.0.3, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +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== + +ms@^2.0.0: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nan@^2.17.0: + version "2.17.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" + integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== + +negotiator@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +node-addon-api@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" + integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== + +node-fetch@^2.6.7: + version "2.6.12" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" + integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== + dependencies: + whatwg-url "^5.0.0" + +node-gyp@8.x: + version "8.4.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" + integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== + dependencies: + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.6" + make-fetch-happen "^9.1.0" + nopt "^5.0.0" + npmlog "^6.0.0" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.2" + which "^2.0.2" + +noop-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/noop-fn/-/noop-fn-1.0.0.tgz#5f33d47f13d2150df93e0cb036699e982f78ffbf" + integrity sha512-pQ8vODlgXt2e7A3mIbFDlizkr46r75V+BJxVAyat8Jl7YmI513gG5cfyRL0FedKraoZ+VAouI1h4/IWpus5pcQ== + +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== + dependencies: + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + +npmlog@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" + integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== + dependencies: + are-we-there-yet "^3.0.0" + console-control-strings "^1.1.0" + gauge "^4.0.3" + set-blocking "^2.0.0" + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +once@^1.3.0, once@^1.3.1: + 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" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +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== + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== + +promise-retry@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" + integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== + dependencies: + err-code "^2.0.2" + retry "^0.12.0" + +punycode@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^6.0.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.5: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +signal-exit@^3.0.0, 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== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" + integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + +socks-proxy-agent@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz#2687a31f9d7185e38d530bef1944fe1f1496d6ce" + integrity sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ== + dependencies: + agent-base "^6.0.2" + debug "^4.3.3" + socks "^2.6.2" + +socks@^2.6.2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" + integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== + dependencies: + ip "^2.0.0" + smart-buffer "^4.2.0" + +sqlite3@^5.0.2: + version "5.1.6" + resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.1.6.tgz#1d4fbc90fe4fbd51e952e0a90fd8f6c2b9098e97" + integrity sha512-olYkWoKFVNSSSQNvxVUfjiVbz3YtBwTJj+mfV5zpHmqW3sELx2Cf4QCdirMelhM5Zh+KDVaKgQHqCxrqiWHybw== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.0" + node-addon-api "^4.2.0" + tar "^6.1.11" + optionalDependencies: + node-gyp "8.x" + +ssri@^8.0.0, ssri@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" + integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== + dependencies: + minipass "^3.1.1" + +"string-width@^1.0.2 || 2 || 3 || 4", 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" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.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" + +sync-promise-expanded@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/sync-promise-expanded/-/sync-promise-expanded-1.0.0.tgz#cbf23f2929124a6cf174979601ef8bf97ed87587" + integrity sha512-pdxxEOaeKO6LghTz0Fe7yw82fx95gtS0SxVgRvIwvN4h9qTie8oOF/pWuH8PGp+PVduS84RXXxO/xrW93Nno9w== + +tar@^6.0.2, tar@^6.1.11, tar@^6.1.2: + version "6.1.15" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.15.tgz#c9738b0b98845a3b344d334b8fa3041aaba53a69" + integrity sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +tiny-queue@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tiny-queue/-/tiny-queue-0.2.1.tgz#25a67f2c6e253b2ca941977b5ef7442ef97a6046" + integrity sha512-EijGsv7kzd9I9g0ByCl6h42BWNGUZrlCSejfrb3AKeHC33SGbASu1VDf5O3rRiiUOhAC9CHdZxFPbZu0HmR70A== + +tr46@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-4.1.1.tgz#281a758dcc82aeb4fe38c7dfe4d11a395aac8469" + integrity sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw== + dependencies: + punycode "^2.3.0" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +typeson-registry@7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/typeson-registry/-/typeson-registry-7.2.1.tgz#2132c7186afceb40bb34250ef7f9337a58bfe96e" + integrity sha512-6KBjzf4kK045pPPA6UqC1O3JKhFM4+O9YZf4AtcBX7v/8m8AG1bB3UIJN05PRY9U3E7P7/4Gc4MjPrqwvGq2wQ== + dependencies: + base64-arraybuffer-es6 "^3.0.0" + typeson "^9.0.2" + whatwg-url "^12.0.1" + +typeson@9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/typeson/-/typeson-9.0.2.tgz#57a9fb6d23976da7048d7d6d665041d72e434e51" + integrity sha512-83w1JVRVt22Kj2bIBo4DyhWYh4RKzbuBW5g89ETlPJOv0+LLX4/hANstDr76srTzULePKSl7DqDAtqHADJOwvQ== + +typeson@^9.0.2: + version "9.0.3" + resolved "https://registry.yarnpkg.com/typeson/-/typeson-9.0.3.tgz#50b2edac0a95c473b7712d5140f622012aa6e163" + integrity sha512-vsOn+VPbIYI3jgj96vwIhAO0BNmlBxEgBKVmuzl1dwXzQe+3XjRi/gK2zYgAansWYlrtvluy4lvWcL8LF01P3Q== + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== + dependencies: + imurmurhash "^0.1.4" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + +websql-configurable@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/websql-configurable/-/websql-configurable-3.0.3.tgz#425bf4a690ef7160d47711caf7531c2183f7d050" + integrity sha512-Fs+3A2BjI3ukkGtvsZcPS4nGoFE0aqors8YKWgICoOt7dcfdeaTdgoMOoFqlEPHc9u/TS9BEFhKP/A9GttB0CQ== + dependencies: + argsarray "^0.0.1" + immediate "^3.2.2" + noop-fn "^1.0.0" + tiny-queue "^0.2.1" + optionalDependencies: + sqlite3 "^5.0.2" + +whatwg-url@^12.0.1: + version "12.0.1" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-12.0.1.tgz#fd7bcc71192e7c3a2a97b9a8d6b094853ed8773c" + integrity sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ== + dependencies: + tr46 "^4.1.1" + webidl-conversions "^7.0.0" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which@^2.0.2: + 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" + +wide-align@^1.1.2, wide-align@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +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== + +ws@^8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/clients/webassembly/internal-dev/.gitignore b/wasm/client/internal-dev/.gitignore similarity index 100% rename from clients/webassembly/internal-dev/.gitignore rename to wasm/client/internal-dev/.gitignore diff --git a/clients/webassembly/internal-dev/bootstrap.js b/wasm/client/internal-dev/bootstrap.js similarity index 100% rename from clients/webassembly/internal-dev/bootstrap.js rename to wasm/client/internal-dev/bootstrap.js diff --git a/clients/webassembly/internal-dev/index.html b/wasm/client/internal-dev/index.html similarity index 86% rename from clients/webassembly/internal-dev/index.html rename to wasm/client/internal-dev/index.html index e9dfb10e0c..8182be7ab6 100644 --- a/clients/webassembly/internal-dev/index.html +++ b/wasm/client/internal-dev/index.html @@ -5,6 +5,7 @@ Nym WebAssembly Demo + @@ -23,8 +24,8 @@

- - + +
@@ -37,7 +38,7 @@

- + \ No newline at end of file diff --git a/clients/webassembly/internal-dev/index.js b/wasm/client/internal-dev/index.js similarity index 91% rename from clients/webassembly/internal-dev/index.js rename to wasm/client/internal-dev/index.js index fa21135309..0ff5c3a191 100644 --- a/clients/webassembly/internal-dev/index.js +++ b/wasm/client/internal-dev/index.js @@ -29,6 +29,10 @@ class WebWorkerClient { const {message, senderTag, isTestPacket } = ev.data.args; displayReceived(message, senderTag, isTestPacket); break; + case 'DisplayString': + const { rawString } = ev.data.args; + displayReceivedRawString(rawString) + break; case 'DisableMagicTestButton': const magicButton = document.querySelector('#magic-button'); magicButton.setAttribute('disabled', "true") @@ -57,14 +61,14 @@ class WebWorkerClient { }); }; - sendTestPacket = (mixnodeIdentity) => { + sendMagicPayload = (mixnodeIdentity) => { if (!this.worker) { console.error('Could not send message because worker does not exist'); return; } this.worker.postMessage({ - kind: 'TestPacket', + kind: 'MagicPayload', args: { mixnodeIdentity, }, @@ -84,7 +88,7 @@ async function main() { const magicButton = document.querySelector('#magic-button'); magicButton.onclick = function () { - sendTestPacket(); + sendMagicPayload(); } } @@ -102,11 +106,11 @@ async function sendMessageTo() { displaySend(message); } -async function sendTestPacket() { - const mixnodeIdentity = document.getElementById('mixnode_identity').value; +async function sendMagicPayload() { + const payload = document.getElementById('magic_payload').value; + await client.sendMagicPayload(payload) - await client.sendTestPacket(mixnodeIdentity) - displaySend(`sending test packets to: ${mixnodeIdentity}...`); + displaySend(`clicked the button and the payload is: ${payload}...`); } /** @@ -146,7 +150,6 @@ function displayReceived(raw, sender_tag, isTestPacket) { displayReceivedRawString(content) } - function displayReceivedRawString(raw) { let timestamp = new Date().toISOString().substr(11, 12); let receivedDiv = document.createElement('div'); diff --git a/clients/webassembly/internal-dev/package.json b/wasm/client/internal-dev/package.json similarity index 89% rename from clients/webassembly/internal-dev/package.json rename to wasm/client/internal-dev/package.json index e505483110..3c15217913 100644 --- a/clients/webassembly/internal-dev/package.json +++ b/wasm/client/internal-dev/package.json @@ -28,13 +28,13 @@ }, "homepage": "https://nymtech.net/docs", "devDependencies": { - "copy-webpack-plugin": "^10.2.4", + "copy-webpack-plugin": "^11.0.0", "hello-wasm-pack": "^0.1.0", "webpack": "^5.70.0", "webpack-cli": "^4.9.2", "webpack-dev-server": "^4.7.4" }, "dependencies": { - "@nymproject/nym-client-wasm": "file:../pkg" + "@nymproject/nym-client-wasm": "file:../../../dist/wasm/client" } } diff --git a/clients/webassembly/internal-dev/webpack.config.js b/wasm/client/internal-dev/webpack.config.js similarity index 83% rename from clients/webassembly/internal-dev/webpack.config.js rename to wasm/client/internal-dev/webpack.config.js index 72329630d0..369c59093f 100644 --- a/clients/webassembly/internal-dev/webpack.config.js +++ b/wasm/client/internal-dev/webpack.config.js @@ -15,14 +15,14 @@ module.exports = { path: path.resolve(__dirname, 'dist'), filename: '[name].js', }, - // mode: 'development', - mode: 'production', + mode: 'development', + // mode: 'production', plugins: [ new CopyWebpackPlugin({ patterns: [ 'index.html', { - from: 'node_modules/@nymproject/nym-client-wasm/*.(js|wasm)', + from: '../../../dist/wasm/client/*.(js|wasm)', to: '[name][ext]', }, ], diff --git a/wasm/client/internal-dev/worker.js b/wasm/client/internal-dev/worker.js new file mode 100644 index 0000000000..3cd3246ee0 --- /dev/null +++ b/wasm/client/internal-dev/worker.js @@ -0,0 +1,316 @@ +// Copyright 2020-2023 Nym Technologies SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +const RUST_WASM_URL = "nym_client_wasm_bg.wasm" + +importScripts('nym_client_wasm.js'); + +console.log('Initializing worker'); + +// wasm_bindgen creates a global variable (with the exports attached) that is in scope after `importScripts` +const { + default_debug, + no_cover_debug, + NymClientBuilder, + NymClient, + set_panic_hook, + ClientConfig, + GatewayEndpointConfig, + current_network_topology, +} = wasm_bindgen; + +let client = null; + +function dummyTopology() { + const l1Mixnode = { + mixId: 1, + owner: 'n1lftjhnl35cjsfd533zhgrwrspx6qmumd8vjgp9', + host: '80.85.86.75', + mixPort: 1789, + identityKey: '91mNjhJSBkJ9Lb6f1iuYMDQPLiX3kAv6paSUCWjGRwQz', + sphinxKey: 'DmfN1mL1T95nPXvLK44AQKCpW1pStHNQCi6Fgpz5dxDV', + layer: 1, + version: '1.1.20', + }; + const l2Mixnode = { + mixId: 2, + owner: 'n18ztkyh20gwzrel0e5m4sahd358fq9p4skwa7d3', + host: '139.162.199.75', + mixPort: 1789, + identityKey: 'BkLhuKQNyPS19sHZ3HHKCTKwK7hCU6XiFLndyZZHiB7s', + sphinxKey: '7KGC97tJRhJZKhDqFcsp4Vu715VVxizuD7BktnzuSmZC', + layer: 2, + version: '1.1.20', + }; + const l3Mixnode = { + mixId: 3, + owner: 'n1njq8h4nndp7ngays5el2rdp22hq67lwqcaq3ph', + host: '139.162.244.139', + identityKey: 'EPja9Kv8JtPHsFbzPdBQierMu5GmQy5roE5njyD6dmND', + sphinxKey: 'HWpsZChDrtEH8XNscW3qJMRzdCfUD8N8DmMcKqFv7tcf', + layer: 3, + }; + + const gateway = { + owner: 'n1d9lclqnfddgg57xe5p0fw4ng54m9f95hal5tlq', + host: '85.159.211.99', + mixPort: 1789, + clientsPort: 9000, + identityKey: '6pXQcG1Jt9hxBzMgTbQL5Y58z6mu4KXVRbA1idmibwsw', + sphinxKey: 'GSdqV7GFSwHWQrVV13pNLMeafTLDVFKBKVPxuhdGrpR3', + version: '1.1.19', + }; + + const mixnodes = new Map(); + mixnodes.set(1, [l1Mixnode]); + mixnodes.set(2, [l2Mixnode]); + mixnodes.set(3, [l3Mixnode]); + + const gateways = [gateway]; + + return { + mixnodes, gateways + } +} + +function printAndDisplayTestResult(result) { + result.log_details(); + + self.postMessage({ + kind: 'DisplayTesterResults', + args: { + score: result.score(), + sentPackets: result.sent_packets, + receivedPackets: result.received_packets, + receivedAcks: result.received_acks, + duplicatePackets: result.duplicate_packets, + duplicateAcks: result.duplicate_acks, + }, + }); +} + +async function testWithNymClient() { + const preferredGateway = "6pXQcG1Jt9hxBzMgTbQL5Y58z6mu4KXVRbA1idmibwsw"; + const topology = dummyTopology() + + let received = 0 + + const onMessageHandler = (message) => { + received += 1; + self.postMessage({ + kind: 'ReceiveMessage', + args: { + message, + senderTag: undefined, + isMagicPayload: true, + }, + }); + + // it's really up to the user to create proper callback here... + console.log(`received ${received} packets so far`) + }; + + console.log('Instantiating WASM client...'); + + let clientBuilder = NymClientBuilder.new_tester(topology, onMessageHandler, preferredGateway) + console.log('Web worker creating WASM client...'); + let local_client = await clientBuilder.start_client(); + console.log('WASM client running!'); + + const selfAddress = local_client.self_address(); + + // set the global (I guess we don't have to anymore?) + client = local_client; + + console.log(`Client address is ${selfAddress}`); + self.postMessage({ + kind: 'Ready', + args: { + selfAddress, + }, + }); + + // Set callback to handle messages passed to the worker. + self.onmessage = async event => { + console.log(event) + if (event.data && event.data.kind) { + switch (event.data.kind) { + case 'SendMessage': { + const {message, recipient} = event.data.args; + let uint8Array = new TextEncoder().encode(message); + await client.send_regular_message(uint8Array, recipient); + break; + } + case 'MagicPayload': { + const {mixnodeIdentity} = event.data.args; + const req = await client.try_construct_test_packet_request(mixnodeIdentity); + await client.change_hardcoded_topology(req.injectable_topology()); + await client.try_send_test_packets(req); + break; + } + } + } + }; +} + +async function wasm_bindgenSetup(onMessageHandler) { + const preferredGateway = "6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; + const validator = 'https://qa-nym-api.qa.nymte.ch/api'; + + // STEP 1. construct config + // those are just some examples, there are obviously more permutations; + // note, the extra optional argument is of the following type: + // /* + // export interface ClientConfigOpts { + // id?: string; + // nymApi?: string; + // nyxd?: string; + // debug?: DebugWasm; + // } + // */ + // + // const debug = no_cover_debug() + // + // #1 + // const config = new ClientConfig({ id: 'my-awesome-client', nymApi: validator, debug: debug} ); + // #2 + // const config = new ClientConfig({ nymApi: validator, debug: debug} ); + // #3 + // const config = new ClientConfig({ id: 'my-awesome-client' } ); + // + // #4 + const differentDebug = default_debug() + const updatedTraffic = differentDebug.traffic; + updatedTraffic.use_extended_packet_size = true + updatedTraffic.average_packet_delay_ms = 666; + differentDebug.traffic = updatedTraffic; + + const config = new ClientConfig( { debug: differentDebug } ); + // + // // STEP 2. setup the client + // // note, the extra optional argument is of the following type: + // /* + // export interface MixFetchOptsSimple { + // preferredGateway?: string; + // storagePassphrase?: string; + // } + // */ + // #1 + // return await NymClient.newWithConfig(config, onMessageHandler) + // + // #2 + return await NymClient.newWithConfig(config, onMessageHandler, { storagePassphrase: "foomp" }) + // + // #3 + // return await NymClient.newWithConfig(config, onMessageHandler, { storagePassphrase: "foomp", preferredGateway }) +} + +async function nativeSetup(onMessageHandler) { + const preferredGateway = "6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; + const validator = 'https://qa-nym-api.qa.nymte.ch/api'; + + // those are just some examples, there are obviously more permutations; + // note, the extra optional argument is of the following type: + /* + export interface ClientOpts extends ClientOptsSimple { + clientId?: string; + nymApiUrl?: string; + nyxdUrl?: string; + clientOverride?: DebugWasmOverride; + } + + where `DebugWasmOverride` is a rather nested struct that you can look up yourself : ) + */ + + // #1 + // return new NymClient(onMessageHandler) + // #2 + // return new NymClient(onMessageHandler, { nymApiUrl: validator }) + // #3 + const noCoverTrafficOverride = { + traffic: { disableMainPoissonPacketDistribution: true }, + coverTraffic: { disableLoopCoverTrafficStream: true }, + } + + return new NymClient(onMessageHandler, { storagePassphrase: "foomp", nymApiUrl: validator, clientId: "my-client", clientOverride: noCoverTrafficOverride } ) +} + +async function normalNymClientUsage() { + self.postMessage({ kind: 'DisableMagicTestButton' }); + + const onMessageHandler = (message) => { + console.log(message); + self.postMessage({ + kind: 'ReceiveMessage', + args: { + message, + }, + }); + }; + + console.log('Instantiating WASM client...'); + // let localClient = await wasm_bindgenSetup(onMessageHandler) + let localClient = await nativeSetup(onMessageHandler) + console.log('WASM client running!'); + + const selfAddress = localClient.self_address(); + + // set the global (I guess we don't have to anymore?) + client = localClient; + + console.log(`Client address is ${selfAddress}`); + self.postMessage({ + kind: 'Ready', + args: { + selfAddress, + }, + }); + + // Set callback to handle messages passed to the worker. + self.onmessage = async event => { + console.log(event) + if (event.data && event.data.kind) { + switch (event.data.kind) { + case 'SendMessage': { + const {message, recipient} = event.data.args; + let uint8Array = new TextEncoder().encode(message); + await client.send_regular_message(uint8Array, recipient); + break; + } + } + } + }; +} + +async function main() { + console.log(">>>>>>>>>>>>>>>>>>>>> JS WORKER MAIN START"); + + // load rust WASM package + await wasm_bindgen(RUST_WASM_URL); + console.log('Loaded RUST WASM'); + + // sets up better stack traces in case of in-rust panics + set_panic_hook(); + // + // hook-up the whole client for testing (not recommended) + // await testWithNymClient() + // + // 'Normal' client setup (to send 'normal' messages) + await normalNymClientUsage() + // + console.log(">>>>>>>>>>>>>>>>>>>>> JS WORKER MAIN END") +} + +// Let's get started! +main(); \ No newline at end of file diff --git a/wasm/client/internal-dev/yarn-error.log b/wasm/client/internal-dev/yarn-error.log new file mode 100644 index 0000000000..d3dea0efe1 --- /dev/null +++ b/wasm/client/internal-dev/yarn-error.log @@ -0,0 +1,2261 @@ +Arguments: + /Users/jedrzej/.nvm/versions/node/v16.20.0/bin/node /Users/jedrzej/.nvm/versions/node/v16.20.0/bin/yarn install + +PATH: + /Users/jedrzej/.nvm/versions/node/v16.20.0/bin:/Library/Frameworks/Python.framework/Versions/3.11/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/Library/Apple/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Users/jedrzej/.cargo/bin:/Users/jedrzej/Library/Application Support/JetBrains/Toolbox/scripts + +Yarn version: + 1.22.19 + +Node version: + 16.20.0 + +Platform: + darwin arm64 + +Trace: + SyntaxError: /Users/jedrzej/workspace/nym/wasm/client/internal-dev/package.json: Unexpected token } in JSON at position 1030 + at JSON.parse () + at /Users/jedrzej/.nvm/versions/node/v16.20.0/lib/node_modules/yarn/lib/cli.js:1629:59 + at Generator.next () + at step (/Users/jedrzej/.nvm/versions/node/v16.20.0/lib/node_modules/yarn/lib/cli.js:310:30) + at /Users/jedrzej/.nvm/versions/node/v16.20.0/lib/node_modules/yarn/lib/cli.js:321:13 + +npm manifest: + { + "name": "create-wasm-app", + "version": "0.1.0", + "description": "create an app to consume rust-generated wasm packages", + "main": "index.js", + "bin": { + "create-wasm-app": ".bin/create-wasm-app.js" + }, + "scripts": { + "build": "webpack --config webpack.config.js", + "build:wasm": "cd ../ && make wasm-build", + "start": "webpack-dev-server --port 8001" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/rustwasm/create-wasm-app.git" + }, + "keywords": [ + "webassembly", + "wasm", + "rust", + "webpack" + ], + "author": "Dave Hrycyszyn ", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/nymtech/nym/issues" + }, + "homepage": "https://nymtech.net/docs", + "devDependencies": { + "copy-webpack-plugin": "^10.2.4", + "hello-wasm-pack": "^0.1.0", + "webpack": "^5.70.0", + "webpack-cli": "^4.9.2", + "webpack-dev-server": "^4.7.4" + }, + "dependencies": { + "@nymproject/nym-client-wasm": "file:../pkg", + } + } + +yarn manifest: + No manifest + +Lockfile: + # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. + # yarn lockfile v1 + + + "@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + + "@jridgewell/gen-mapping@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + + "@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + + "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + + "@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + + "@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + + "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + + "@leichtgewicht/ip-codec@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" + integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + + "@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + + "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + + "@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + + "@nymproject/nym-client-wasm@file:../pkg": + version "1.1.1" + + "@types/body-parser@*": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + + "@types/bonjour@^3.5.9": + version "3.5.10" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" + integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + dependencies: + "@types/node" "*" + + "@types/connect-history-api-fallback@^1.3.5": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" + integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + + "@types/connect@*": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" + + "@types/eslint-scope@^3.7.3": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + + "@types/eslint@*": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.37.0.tgz#29cebc6c2a3ac7fea7113207bf5a828fdf4d7ef1" + integrity sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + + "@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + + "@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + + "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": + version "4.17.33" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz#de35d30a9d637dc1450ad18dd583d75d5733d543" + integrity sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + + "@types/express@*", "@types/express@^4.17.13": + version "4.17.17" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4" + integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + + "@types/http-proxy@^1.17.8": + version "1.17.10" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.10.tgz#e576c8e4a0cc5c6a138819025a88e167ebb38d6c" + integrity sha512-Qs5aULi+zV1bwKAg5z1PWnDXWmsn+LxIvUGv6E2+OOMYhclZMO+OXd9pYVf2gLykf2I7IV2u7oTHwChPNsvJ7g== + dependencies: + "@types/node" "*" + + "@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + + "@types/mime@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" + integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== + + "@types/node@*": + version "18.15.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" + integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q== + + "@types/qs@*": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + + "@types/range-parser@*": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + + "@types/retry@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" + integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== + + "@types/serve-index@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" + integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + dependencies: + "@types/express" "*" + + "@types/serve-static@*", "@types/serve-static@^1.13.10": + version "1.15.1" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.1.tgz#86b1753f0be4f9a1bee68d459fcda5be4ea52b5d" + integrity sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ== + dependencies: + "@types/mime" "*" + "@types/node" "*" + + "@types/sockjs@^0.3.33": + version "0.3.33" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" + integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + dependencies: + "@types/node" "*" + + "@types/ws@^8.5.1": + version "8.5.4" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5" + integrity sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg== + dependencies: + "@types/node" "*" + + "@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + + "@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + + "@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + + "@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + + "@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + + "@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + + "@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + + "@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + + "@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + + "@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + + "@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + + "@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + + "@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + + "@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + + "@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@xtuc/long" "4.2.2" + + "@webpack-cli/configtest@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" + integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== + + "@webpack-cli/info@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" + integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== + dependencies: + envinfo "^7.7.3" + + "@webpack-cli/serve@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" + integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== + + "@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + + "@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + + accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + + acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + + acorn@^8.5.0, acorn@^8.7.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + + ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + + ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + + ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + + ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + + ajv@^8.0.0, ajv@^8.8.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + + ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + + anymatch@~3.1.2: + 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" + + array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + + array-flatten@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + + array-union@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" + integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== + + 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== + + batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== + + binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + + body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + + bonjour-service@^1.0.11: + version "1.1.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.1.1.tgz#960948fa0e0153f5d26743ab15baf8e33752c135" + integrity sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg== + dependencies: + array-flatten "^2.1.2" + dns-equal "^1.0.0" + fast-deep-equal "^3.1.3" + multicast-dns "^7.2.5" + + 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" + + braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + + browserslist@^4.14.5: + version "4.21.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" + integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== + dependencies: + caniuse-lite "^1.0.30001449" + electron-to-chromium "^1.4.284" + node-releases "^2.0.8" + update-browserslist-db "^1.0.10" + + 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== + + bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + + bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + + call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + + caniuse-lite@^1.0.30001449: + version "1.0.30001474" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001474.tgz#13b6fe301a831fe666cce8ca4ef89352334133d5" + integrity sha512-iaIZ8gVrWfemh5DG3T9/YqarVZoYf0r188IjaGwx68j4Pf0SGY6CQkmJUIE+NZHkkecQGohzXmBGEwWDr9aM3Q== + + chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + + chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + + clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + + colorette@^2.0.10, colorette@^2.0.14: + version "2.0.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + + commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + + commander@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + + compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + + compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + + 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== + + connect-history-api-fallback@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" + integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== + + content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + + content-type@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + + cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + + cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + + copy-webpack-plugin@^10.2.4: + version "10.2.4" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe" + integrity sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg== + dependencies: + fast-glob "^3.2.7" + glob-parent "^6.0.1" + globby "^12.0.2" + normalize-path "^3.0.0" + schema-utils "^4.0.0" + serialize-javascript "^6.0.0" + + core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + + 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" + + debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + + debug@^4.1.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + + default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== + dependencies: + execa "^5.0.0" + + define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + + depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + + depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + + destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + + detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + + dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + + dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== + + dns-packet@^5.2.2: + version "5.5.0" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.5.0.tgz#f59cbf3396c130957c56a6ad5fd3959ccdc30065" + integrity sha512-USawdAUzRkV6xrqTjiAEp6M9YagZEzWcSUaZTcIFAiyQWW1SoI6KyId8y2+/71wbgHKQAKd+iupLv4YvEwYWvA== + dependencies: + "@leichtgewicht/ip-codec" "^2.0.1" + + ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + + electron-to-chromium@^1.4.284: + version "1.4.352" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.352.tgz#be96bd7c2f4b980deebc9338a49a67430a33ed73" + integrity sha512-ikFUEyu5/q+wJpMOxWxTaEVk2M1qKqTGKKyfJmod1CPZxKfYnxVS41/GCBQg21ItBpZybyN8sNpRqCUGm+Zc4Q== + + encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + + enhanced-resolve@^5.10.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" + integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + + envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + + es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + + escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + + escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + + eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + + esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + + estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + + estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + + etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + + eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + + events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + + 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" + + express@^4.17.3: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + + fast-glob@^3.2.7: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + + fast-json-stable-stringify@^2.0.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== + + fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + + fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + + faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + + fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + + finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + + find-up@^4.0.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" + + follow-redirects@^1.0.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + + forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + + fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + + fs-monkey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" + integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== + + 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.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + + function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + + get-intrinsic@^1.0.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + + 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-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + + glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + + glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + + glob@^7.1.3: + 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" + + globby@^12.0.2: + version "12.2.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" + integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== + dependencies: + array-union "^3.0.1" + dir-glob "^3.0.1" + fast-glob "^3.2.7" + ignore "^5.1.9" + merge2 "^1.4.1" + slash "^4.0.0" + + "go-mix-conn@file:../go-mix-conn/build": + version "0.0.0" + + graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6, 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== + + handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== + + 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-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== + + has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + + hello-wasm-pack@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/hello-wasm-pack/-/hello-wasm-pack-0.1.0.tgz#482a2e3371828056ac35f5b5fec76c0b99dcd530" + integrity sha512-3hx0GDkDLf/a9ThCMV2qG4mwza8N/MCtm8aeFFc/cdBCL2zMJ1kW1wjNl7xPqD1lz8Yl5+uhnc/cpui4dLwz/w== + + hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + + html-entities@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" + integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== + + http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== + + http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + + http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + + http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + + http-proxy-middleware@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" + integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + dependencies: + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" + + http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + + 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== + + iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + + ignore@^5.1.9: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + + import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + + 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, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + + inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + + interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + + ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + + ipaddr.js@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" + integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== + + is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + + is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + + is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + + is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + + is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + + 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-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + + is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + + 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== + + is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + + isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + + isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + + isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + + jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + + json-parse-even-better-errors@^2.3.1: + 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-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + + json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + + kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + + launch-editor@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.0.tgz#4c0c1a6ac126c572bd9ff9a30da1d2cae66defd7" + integrity sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ== + dependencies: + picocolors "^1.0.0" + shell-quote "^1.7.3" + + loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + + 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" + + media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + + memfs@^3.4.3: + version "3.4.13" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.13.tgz#248a8bd239b3c240175cd5ec548de5227fc4f345" + integrity sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg== + dependencies: + fs-monkey "^1.0.3" + + merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + + 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== + + merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + + 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.2, micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + + mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + 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.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + 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@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + + 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== + + minimalistic-assert@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + + minimatch@^3.1.1: + 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" + + ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + + 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== + + ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + + multicast-dns@^7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" + integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== + dependencies: + dns-packet "^5.2.2" + thunky "^1.0.2" + + negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + + neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + + node-forge@^1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + + node-releases@^2.0.8: + version "2.0.10" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" + integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== + + normalize-path@^3.0.0, 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.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + + obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + + on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + + on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + + once@^1.3.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" + + open@^8.0.9: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.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-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-retry@^4.5.0: + version "4.6.2" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" + integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== + dependencies: + "@types/retry" "0.12.0" + retry "^0.13.1" + + 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== + + parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + + 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== + + path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + + path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + + picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + + 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" + + process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + + proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + + punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + + qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + + queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + + randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + + range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + + raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + + readable-stream@^2.0.1: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + + readable-stream@^3.0.6: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + + readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + + rechoir@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" + integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== + dependencies: + resolve "^1.9.0" + + require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + + requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + + 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@^1.9.0: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + + retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + + reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + + rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + + run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + + safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + + "safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + + schema-utils@^3.1.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + + schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + + select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== + + selfsigned@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" + integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== + dependencies: + node-forge "^1" + + send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + + serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" + integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== + dependencies: + randombytes "^2.1.0" + + serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + + serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + + setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + + setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + + shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.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== + + shell-quote@^1.7.3: + version "1.8.0" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.0.tgz#20d078d0eaf71d54f43bd2ba14a1b5b9bfa5c8ba" + integrity sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ== + + side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + + signal-exit@^3.0.3: + 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== + + slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + + sockjs@^0.3.24: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + + source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + + source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + + spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + + spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + + statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + + "statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + + string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + + string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + + 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== + + 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== + + tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + + terser-webpack-plugin@^5.1.3: + version "5.3.7" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz#ef760632d24991760f339fe9290deb936ad1ffc7" + integrity sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.17" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.16.5" + + terser@^5.16.5: + version "5.16.8" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.8.tgz#ccde583dabe71df3f4ed02b65eb6532e0fae15d5" + integrity sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA== + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + commander "^2.20.0" + source-map-support "~0.5.20" + + thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + + 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" + + toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + + type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + + unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + + update-browserslist-db@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + + uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + + util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + + utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + + uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + + vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + + watchpack@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + + wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + + webpack-cli@^4.9.2: + version "4.10.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" + integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.2.0" + "@webpack-cli/info" "^1.5.0" + "@webpack-cli/serve" "^1.7.0" + colorette "^2.0.14" + commander "^7.0.0" + cross-spawn "^7.0.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + webpack-merge "^5.7.3" + + webpack-dev-middleware@^5.3.1: + version "5.3.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" + integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== + dependencies: + colorette "^2.0.10" + memfs "^3.4.3" + mime-types "^2.1.31" + range-parser "^1.2.1" + schema-utils "^4.0.0" + + webpack-dev-server@^4.7.4: + version "4.13.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.13.2.tgz#d97445481d78691efe6d9a3b230833d802fc31f9" + integrity sha512-5i6TrGBRxG4vnfDpB6qSQGfnB6skGBXNL5/542w2uRGLimX6qeE5BQMLrzIC3JYV/xlGOv+s+hTleI9AZKUQNw== + dependencies: + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/express" "^4.17.13" + "@types/serve-index" "^1.9.1" + "@types/serve-static" "^1.13.10" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.5.1" + ansi-html-community "^0.0.8" + bonjour-service "^1.0.11" + chokidar "^3.5.3" + colorette "^2.0.10" + compression "^1.7.4" + connect-history-api-fallback "^2.0.0" + default-gateway "^6.0.3" + express "^4.17.3" + graceful-fs "^4.2.6" + html-entities "^2.3.2" + http-proxy-middleware "^2.0.3" + ipaddr.js "^2.0.1" + launch-editor "^2.6.0" + open "^8.0.9" + p-retry "^4.5.0" + rimraf "^3.0.2" + schema-utils "^4.0.0" + selfsigned "^2.1.1" + serve-index "^1.9.1" + sockjs "^0.3.24" + spdy "^4.0.2" + webpack-dev-middleware "^5.3.1" + ws "^8.13.0" + + webpack-merge@^5.7.3: + version "5.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + + webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + + webpack@^5.70.0: + version "5.77.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.77.0.tgz#dea3ad16d7ea6b84aa55fa42f4eac9f30e7eb9b4" + integrity sha512-sbGNjBr5Ya5ss91yzjeJTLKyfiwo5C628AFjEa6WSXcZa4E+F57om3Cc8xLb1Jh0b243AWuSYRf3dn7HVeFQ9Q== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.7.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.10.0" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.4.0" + webpack-sources "^3.2.3" + + websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + + websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + + 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" + + wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + + 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== + + ws@^8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== diff --git a/wasm/client/internal-dev/yarn.lock b/wasm/client/internal-dev/yarn.lock new file mode 100644 index 0000000000..3555ea6145 --- /dev/null +++ b/wasm/client/internal-dev/yarn.lock @@ -0,0 +1,2189 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + +"@jridgewell/gen-mapping@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@leichtgewicht/ip-codec@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" + integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nymproject/nym-client-wasm@file:../../../dist/wasm/client": + version "1.1.1" + +"@types/body-parser@*": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/bonjour@^3.5.9": + version "3.5.10" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" + integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + dependencies: + "@types/node" "*" + +"@types/connect-history-api-fallback@^1.3.5": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" + integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" + +"@types/eslint-scope@^3.7.3": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.37.0.tgz#29cebc6c2a3ac7fea7113207bf5a828fdf4d7ef1" + integrity sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + +"@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": + version "4.17.33" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz#de35d30a9d637dc1450ad18dd583d75d5733d543" + integrity sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@*", "@types/express@^4.17.13": + version "4.17.17" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4" + integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/http-proxy@^1.17.8": + version "1.17.10" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.10.tgz#e576c8e4a0cc5c6a138819025a88e167ebb38d6c" + integrity sha512-Qs5aULi+zV1bwKAg5z1PWnDXWmsn+LxIvUGv6E2+OOMYhclZMO+OXd9pYVf2gLykf2I7IV2u7oTHwChPNsvJ7g== + dependencies: + "@types/node" "*" + +"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/mime@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" + integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== + +"@types/node@*": + version "18.15.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" + integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q== + +"@types/qs@*": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/range-parser@*": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + +"@types/retry@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" + integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== + +"@types/serve-index@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" + integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + dependencies: + "@types/express" "*" + +"@types/serve-static@*", "@types/serve-static@^1.13.10": + version "1.15.1" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.1.tgz#86b1753f0be4f9a1bee68d459fcda5be4ea52b5d" + integrity sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ== + dependencies: + "@types/mime" "*" + "@types/node" "*" + +"@types/sockjs@^0.3.33": + version "0.3.33" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" + integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + dependencies: + "@types/node" "*" + +"@types/ws@^8.5.1": + version "8.5.4" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5" + integrity sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg== + dependencies: + "@types/node" "*" + +"@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + +"@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + +"@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + +"@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + +"@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + +"@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + +"@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + +"@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + +"@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + +"@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" + integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== + +"@webpack-cli/info@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" + integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" + integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + +acorn@^8.5.0, acorn@^8.7.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.0, ajv@^8.8.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + +anymatch@~3.1.2: + 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" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +array-flatten@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + +array-union@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" + integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== + +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== + +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +bonjour-service@^1.0.11: + version "1.1.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.1.1.tgz#960948fa0e0153f5d26743ab15baf8e33752c135" + integrity sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg== + dependencies: + array-flatten "^2.1.2" + dns-equal "^1.0.0" + fast-deep-equal "^3.1.3" + multicast-dns "^7.2.5" + +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" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.14.5: + version "4.21.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" + integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== + dependencies: + caniuse-lite "^1.0.30001449" + electron-to-chromium "^1.4.284" + node-releases "^2.0.8" + update-browserslist-db "^1.0.10" + +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== + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +caniuse-lite@^1.0.30001449: + version "1.0.30001474" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001474.tgz#13b6fe301a831fe666cce8ca4ef89352334133d5" + integrity sha512-iaIZ8gVrWfemh5DG3T9/YqarVZoYf0r188IjaGwx68j4Pf0SGY6CQkmJUIE+NZHkkecQGohzXmBGEwWDr9aM3Q== + +chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +colorette@^2.0.10, colorette@^2.0.14: + version "2.0.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +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== + +connect-history-api-fallback@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" + integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +copy-webpack-plugin@^10.2.4: + version "10.2.4" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe" + integrity sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg== + dependencies: + fast-glob "^3.2.7" + glob-parent "^6.0.1" + globby "^12.0.2" + normalize-path "^3.0.0" + schema-utils "^4.0.0" + serialize-javascript "^6.0.0" + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +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" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^4.1.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== + dependencies: + execa "^5.0.0" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== + +dns-packet@^5.2.2: + version "5.5.0" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.5.0.tgz#f59cbf3396c130957c56a6ad5fd3959ccdc30065" + integrity sha512-USawdAUzRkV6xrqTjiAEp6M9YagZEzWcSUaZTcIFAiyQWW1SoI6KyId8y2+/71wbgHKQAKd+iupLv4YvEwYWvA== + dependencies: + "@leichtgewicht/ip-codec" "^2.0.1" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.284: + version "1.4.352" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.352.tgz#be96bd7c2f4b980deebc9338a49a67430a33ed73" + integrity sha512-ikFUEyu5/q+wJpMOxWxTaEVk2M1qKqTGKKyfJmod1CPZxKfYnxVS41/GCBQg21ItBpZybyN8sNpRqCUGm+Zc4Q== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +enhanced-resolve@^5.10.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" + integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +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" + +express@^4.17.3: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.7: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.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== + +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-up@^4.0.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" + +follow-redirects@^1.0.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-monkey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" + integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== + +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.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-intrinsic@^1.0.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +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-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@^7.1.3: + 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" + +globby@^12.0.2: + version "12.2.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" + integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== + dependencies: + array-union "^3.0.1" + dir-glob "^3.0.1" + fast-glob "^3.2.7" + ignore "^5.1.9" + merge2 "^1.4.1" + slash "^4.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6, 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== + +handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== + +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-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== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hello-wasm-pack@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/hello-wasm-pack/-/hello-wasm-pack-0.1.0.tgz#482a2e3371828056ac35f5b5fec76c0b99dcd530" + integrity sha512-3hx0GDkDLf/a9ThCMV2qG4mwza8N/MCtm8aeFFc/cdBCL2zMJ1kW1wjNl7xPqD1lz8Yl5+uhnc/cpui4dLwz/w== + +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + +html-entities@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" + integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== + +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + +http-proxy-middleware@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" + integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + dependencies: + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" + +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +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== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore@^5.1.9: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +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, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + +interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +ipaddr.js@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" + integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +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-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +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== + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +json-parse-even-better-errors@^2.3.1: + 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-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +launch-editor@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.0.tgz#4c0c1a6ac126c572bd9ff9a30da1d2cae66defd7" + integrity sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ== + dependencies: + picocolors "^1.0.0" + shell-quote "^1.7.3" + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +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" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +memfs@^3.4.3: + version "3.4.13" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.13.tgz#248a8bd239b3c240175cd5ec548de5227fc4f345" + integrity sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg== + dependencies: + fs-monkey "^1.0.3" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +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== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +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.2, micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + 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.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + 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@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +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== + +minimalistic-assert@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimatch@^3.1.1: + 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" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +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== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multicast-dns@^7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" + integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== + dependencies: + dns-packet "^5.2.2" + thunky "^1.0.2" + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-forge@^1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + +node-releases@^2.0.8: + version "2.0.10" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" + integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== + +normalize-path@^3.0.0, 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.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.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" + +open@^8.0.9: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.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-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-retry@^4.5.0: + version "4.6.2" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" + integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== + dependencies: + "@types/retry" "0.12.0" + retry "^0.13.1" + +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== + +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +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== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +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" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +readable-stream@^2.0.1: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +rechoir@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" + integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== + dependencies: + resolve "^1.9.0" + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +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@^1.9.0: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +schema-utils@^3.1.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== + +selfsigned@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" + integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== + dependencies: + node-forge "^1" + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" + integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== + dependencies: + randombytes "^2.1.0" + +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.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== + +shell-quote@^1.7.3: + version "1.8.0" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.0.tgz#20d078d0eaf71d54f43bd2ba14a1b5b9bfa5c8ba" + integrity sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.3: + 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== + +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + +sockjs@^0.3.24: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +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== + +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== + +tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +terser-webpack-plugin@^5.1.3: + version "5.3.7" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz#ef760632d24991760f339fe9290deb936ad1ffc7" + integrity sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.17" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.16.5" + +terser@^5.16.5: + version "5.16.8" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.8.tgz#ccde583dabe71df3f4ed02b65eb6532e0fae15d5" + integrity sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA== + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + commander "^2.20.0" + source-map-support "~0.5.20" + +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + +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" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +update-browserslist-db@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +watchpack@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + +webpack-cli@^4.9.2: + version "4.10.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" + integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.2.0" + "@webpack-cli/info" "^1.5.0" + "@webpack-cli/serve" "^1.7.0" + colorette "^2.0.14" + commander "^7.0.0" + cross-spawn "^7.0.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + webpack-merge "^5.7.3" + +webpack-dev-middleware@^5.3.1: + version "5.3.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" + integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== + dependencies: + colorette "^2.0.10" + memfs "^3.4.3" + mime-types "^2.1.31" + range-parser "^1.2.1" + schema-utils "^4.0.0" + +webpack-dev-server@^4.7.4: + version "4.13.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.13.2.tgz#d97445481d78691efe6d9a3b230833d802fc31f9" + integrity sha512-5i6TrGBRxG4vnfDpB6qSQGfnB6skGBXNL5/542w2uRGLimX6qeE5BQMLrzIC3JYV/xlGOv+s+hTleI9AZKUQNw== + dependencies: + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/express" "^4.17.13" + "@types/serve-index" "^1.9.1" + "@types/serve-static" "^1.13.10" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.5.1" + ansi-html-community "^0.0.8" + bonjour-service "^1.0.11" + chokidar "^3.5.3" + colorette "^2.0.10" + compression "^1.7.4" + connect-history-api-fallback "^2.0.0" + default-gateway "^6.0.3" + express "^4.17.3" + graceful-fs "^4.2.6" + html-entities "^2.3.2" + http-proxy-middleware "^2.0.3" + ipaddr.js "^2.0.1" + launch-editor "^2.6.0" + open "^8.0.9" + p-retry "^4.5.0" + rimraf "^3.0.2" + schema-utils "^4.0.0" + selfsigned "^2.1.1" + serve-index "^1.9.1" + sockjs "^0.3.24" + spdy "^4.0.2" + webpack-dev-middleware "^5.3.1" + ws "^8.13.0" + +webpack-merge@^5.7.3: + version "5.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@^5.70.0: + version "5.77.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.77.0.tgz#dea3ad16d7ea6b84aa55fa42f4eac9f30e7eb9b4" + integrity sha512-sbGNjBr5Ya5ss91yzjeJTLKyfiwo5C628AFjEa6WSXcZa4E+F57om3Cc8xLb1Jh0b243AWuSYRf3dn7HVeFQ9Q== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.7.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.10.0" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.4.0" + webpack-sources "^3.2.3" + +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +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" + +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + +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== + +ws@^8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== diff --git a/clients/webassembly/src/client/mod.rs b/wasm/client/src/client.rs similarity index 63% rename from clients/webassembly/src/client/mod.rs rename to wasm/client/src/client.rs index 733521ea97..e736d972b2 100644 --- a/clients/webassembly/src/client/mod.rs +++ b/wasm/client/src/client.rs @@ -1,41 +1,45 @@ // Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use self::config::Config; -use crate::client::helpers::{InputSender, NymClientTestRequest, WasmTopologyExt}; -use crate::client::response_pusher::ResponsePusher; -use crate::constants::NODE_TESTER_CLIENT_ID; +use crate::config::{ClientConfig, ClientConfigOpts}; use crate::error::WasmClientError; -use crate::helpers::{ - parse_recipient, parse_sender_tag, setup_from_topology, setup_gateway_from_api, - setup_reply_surb_storage_backend, -}; -use crate::storage::traits::FullWasmClientStorage; -use crate::storage::ClientStorage; -use crate::topology::WasmNymTopology; +use crate::helpers::{InputSender, WasmTopologyExt}; +use crate::response_pusher::ResponsePusher; use js_sys::Promise; -use nym_client_core::client::base_client::{ - BaseClientBuilder, ClientInput, ClientOutput, ClientState, -}; -use nym_client_core::client::inbound_messages::InputMessage; -use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage; -use nym_sphinx::params::PacketType; -use nym_task::connections::TransmissionLane; -use nym_task::TaskManager; -use nym_topology::provider_trait::{HardcodedTopologyProvider, TopologyProvider}; -use nym_topology::NymTopology; -use nym_validator_client::client::IdentityKey; -use nym_validator_client::QueryReqwestRpcNyxdClient; -use rand::rngs::OsRng; -use rand::RngCore; +use serde::{Deserialize, Serialize}; use std::sync::Arc; +use tsify::Tsify; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; -use wasm_utils::{check_promise_result, console_log, PromisableResult}; +use wasm_client_core::client::{ + base_client::{BaseClientBuilder, ClientInput, ClientOutput, ClientState}, + inbound_messages::InputMessage, +}; +use wasm_client_core::config::r#override::DebugWasmOverride; +use wasm_client_core::helpers::{ + parse_recipient, parse_sender_tag, setup_from_topology, setup_gateway_from_api, +}; +use wasm_client_core::init::GatewaySetup; +use wasm_client_core::nym_task::connections::TransmissionLane; +use wasm_client_core::nym_task::TaskManager; +use wasm_client_core::storage::core_client_traits::FullWasmClientStorage; +use wasm_client_core::storage::ClientStorage; +use wasm_client_core::topology::WasmNymTopology; +use wasm_client_core::{ + HardcodedTopologyProvider, IdentityKey, NymTopology, PacketType, QueryReqwestRpcNyxdClient, + TopologyProvider, +}; +use wasm_utils::error::PromisableResult; +use wasm_utils::{check_promise_result, console_log}; -pub mod config; -mod helpers; -mod response_pusher; +#[cfg(feature = "node-tester")] +use crate::helpers::{NymClientTestRequest, WasmTopologyTestExt}; + +#[cfg(feature = "node-tester")] +use rand::{rngs::OsRng, RngCore}; + +#[cfg(feature = "node-tester")] +pub(crate) const NODE_TESTER_CLIENT_ID: &str = "_nym-node-tester-client"; #[wasm_bindgen] pub struct NymClient { @@ -54,9 +58,11 @@ pub struct NymClient { packet_type: PacketType, } +// TODO: we don't really need a builder anymore, +// but we might as well leave it for backwards compatibility #[wasm_bindgen] pub struct NymClientBuilder { - config: Config, + config: ClientConfig, custom_topology: Option, preferred_gateway: Option, @@ -68,7 +74,7 @@ pub struct NymClientBuilder { impl NymClientBuilder { #[wasm_bindgen(constructor)] pub fn new( - config: Config, + config: ClientConfig, on_message: js_sys::Function, preferred_gateway: Option, storage_passphrase: Option, @@ -78,6 +84,7 @@ impl NymClientBuilder { custom_topology: None, storage_passphrase, on_message, + // on_mix_fetch_message: Some(on_mix_fetch_message), preferred_gateway, } } @@ -86,26 +93,27 @@ impl NymClientBuilder { // no poisson delay // hardcoded topology // NOTE: you most likely want to use `[NymNodeTester]` instead. + #[cfg(feature = "node-tester")] pub fn new_tester( topology: WasmNymTopology, on_message: js_sys::Function, gateway: Option, - ) -> Self { + ) -> Result { if let Some(gateway_id) = &gateway { if !topology.ensure_contains_gateway_id(gateway_id) { panic!("the specified topology does not contain the gateway used by the client") } } - let full_config = Config::new_tester_config(NODE_TESTER_CLIENT_ID); + let full_config = ClientConfig::new_tester_config(NODE_TESTER_CLIENT_ID); - NymClientBuilder { + Ok(NymClientBuilder { config: full_config, - custom_topology: Some(topology.into()), + custom_topology: Some(topology.try_into()?), on_message, storage_passphrase: None, preferred_gateway: gateway, - } + }) } fn start_reconstructed_pusher(client_output: ClientOutput, on_message: js_sys::Function) { @@ -120,12 +128,11 @@ impl NymClientBuilder { } } - fn initialise_storage(config: &Config, base_storage: ClientStorage) -> FullWasmClientStorage { - FullWasmClientStorage { - keys_and_gateway_store: base_storage, - reply_storage: setup_reply_surb_storage_backend(config.base.debug.reply_surbs), - credential_storage: EphemeralCredentialStorage::default(), - } + fn initialise_storage( + config: &ClientConfig, + base_storage: ClientStorage, + ) -> FullWasmClientStorage { + FullWasmClientStorage::new(&config.base, base_storage) } async fn start_client_async(mut self) -> Result { @@ -141,7 +148,7 @@ impl NymClientBuilder { let user_chosen = self.preferred_gateway.clone(); // if we provided hardcoded topology, get gateway from it, otherwise get it the 'standard' way - if let Some(topology) = &self.custom_topology { + let init_res = if let Some(topology) = &self.custom_topology { setup_from_topology(user_chosen, topology, &client_store).await? } else { setup_gateway_from_api(&client_store, user_chosen, &nym_api_endpoints).await? @@ -151,15 +158,20 @@ impl NymClientBuilder { let storage = Self::initialise_storage(&self.config, client_store); let maybe_topology_provider = self.topology_provider(); - let mut base_builder: BaseClientBuilder<_, FullWasmClientStorage> = - BaseClientBuilder::::new( - &self.config.base, - storage, - None, - ); + let mut base_builder = BaseClientBuilder::::new( + &self.config.base, + storage, + None, + ); if let Some(topology_provider) = maybe_topology_provider { base_builder = base_builder.with_topology_provider(topology_provider); } + if let Some(authenticated_ephemeral_client) = init_res.authenticated_ephemeral_client { + base_builder = base_builder.with_gateway_setup(GatewaySetup::ReuseConnection { + authenticated_ephemeral_client, + details: init_res.details, + }); + } let mut started_client = base_builder.start_base().await?; let self_address = started_client.address.to_string(); @@ -184,38 +196,113 @@ impl NymClientBuilder { } } +#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct ClientOptsSimple { + // ideally we'd have used the `IdentityKey` type alias, but that'd be extremely annoying to get working in TS + #[tsify(optional)] + pub(crate) preferred_gateway: Option, + + #[tsify(optional)] + pub(crate) storage_passphrase: Option, +} + +#[derive(Tsify, Debug, Default, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct ClientOpts { + #[serde(flatten)] + pub(crate) base: Option, + + #[tsify(optional)] + pub(crate) client_id: Option, + + #[tsify(optional)] + pub(crate) nym_api_url: Option, + + // currently not used, but will be required once we have coconut + #[tsify(optional)] + pub(crate) nyxd_url: Option, + + #[tsify(optional)] + pub(crate) client_override: Option, +} + +impl<'a> From<&'a ClientOpts> for ClientConfigOpts { + fn from(value: &'a ClientOpts) -> Self { + ClientConfigOpts { + id: value.client_id.as_ref().map(|v| v.to_owned()), + nym_api: value.nym_api_url.as_ref().map(|v| v.to_owned()), + nyxd: value.nyxd_url.as_ref().map(|v| v.to_owned()), + debug: value.client_override.as_ref().map(|&v| v.into()), + } + } +} + #[wasm_bindgen] impl NymClient { async fn _new( - config: Config, + config: ClientConfig, on_message: js_sys::Function, - preferred_gateway: Option, - storage_passphrase: Option, + opts: Option, ) -> Result { - NymClientBuilder::new(config, on_message, preferred_gateway, storage_passphrase) - .start_client_async() - .await + if let Some(opts) = opts { + let preferred_gateway = opts.preferred_gateway; + let storage_passphrase = opts.storage_passphrase; + NymClientBuilder::new(config, on_message, preferred_gateway, storage_passphrase) + } else { + NymClientBuilder::new(config, on_message, None, None) + } + .start_client_async() + .await } #[wasm_bindgen(constructor)] #[allow(clippy::new_ret_no_self)] - pub fn new( - config: Config, - on_message: js_sys::Function, - preferred_gateway: Option, - storage_passphrase: Option, - ) -> Promise { + pub fn new(on_message: js_sys::Function, opts: Option) -> Promise { + let opts = opts.unwrap_or_default(); + let mut config = check_promise_result!(ClientConfig::new((&opts).into())); + + if let Some(dbg) = opts.client_override { + config.override_debug(dbg); + } + future_to_promise(async move { - Self::_new(config, on_message, preferred_gateway, storage_passphrase) + Self::_new(config, on_message, opts.base) .await .into_promise_result() }) } + #[wasm_bindgen(js_name = "newWithConfig")] + pub fn new_with_config( + config: ClientConfig, + on_message: js_sys::Function, + opts: ClientOptsSimple, + ) -> Promise { + future_to_promise(async move { + Self::_new(config, on_message, Some(opts)) + .await + .into_promise_result() + }) + } + + // no cover traffic + // no poisson delay + // hardcoded topology + // NOTE: you most likely want to use `[NymNodeTester]` instead. + #[cfg(feature = "node-tester")] + #[wasm_bindgen(js_name = "newTester")] + pub fn new_tester() -> Promise { + todo!() + } + pub fn self_address(&self) -> String { self.self_address.clone() } + #[cfg(feature = "node-tester")] pub fn try_construct_test_packet_request( &self, mixnode_identity: String, @@ -239,6 +326,7 @@ impl NymClient { /// Sends a test packet through the current network topology. /// It's the responsibility of the caller to ensure the correct topology has been injected and /// correct onmessage handlers have been setup. + #[cfg(feature = "node-tester")] pub fn try_send_test_packets(&mut self, request: NymClientTestRequest) -> Promise { // TOOD: use the premade packets instead console_log!( diff --git a/wasm/client/src/config.rs b/wasm/client/src/config.rs new file mode 100644 index 0000000000..da33746d34 --- /dev/null +++ b/wasm/client/src/config.rs @@ -0,0 +1,63 @@ +// Copyright 2022-2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::error::WasmClientError; +use serde::{Deserialize, Serialize}; +use tsify::Tsify; +use wasm_bindgen::prelude::*; +use wasm_client_core::config::{new_base_client_config, BaseClientConfig, ConfigDebug, DebugWasm}; + +pub const DEFAULT_CLIENT_ID: &str = "nym-mixnet-client"; + +#[wasm_bindgen] +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct ClientConfig { + pub(crate) base: BaseClientConfig, +} + +#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct ClientConfigOpts { + #[tsify(optional)] + pub id: Option, + + #[tsify(optional)] + pub nym_api: Option, + + #[tsify(optional)] + pub nyxd: Option, + + #[tsify(optional)] + pub debug: Option, +} + +#[wasm_bindgen] +impl ClientConfig { + #[wasm_bindgen(constructor)] + pub fn new(opts: ClientConfigOpts) -> Result { + let version = env!("CARGO_PKG_VERSION").to_string(); + let id = opts.id.unwrap_or_else(|| DEFAULT_CLIENT_ID.to_string()); + + Ok(ClientConfig { + base: new_base_client_config(id, version, opts.nym_api, opts.nyxd, opts.debug)?, + }) + } + + #[cfg(feature = "node-tester")] + pub(crate) fn new_tester_config>(id: S) -> Self { + ClientConfig { + base: BaseClientConfig::new(id.into(), env!("CARGO_PKG_VERSION").to_string()) + .with_disabled_credentials(true) + .with_disabled_cover_traffic(true) + .with_disabled_topology_refresh(true), + } + } +} + +impl ClientConfig { + pub fn override_debug>(&mut self, debug: D) { + self.base.debug = debug.into(); + } +} diff --git a/clients/webassembly/src/encoded_payload_helper.rs b/wasm/client/src/encoded_payload_helper.rs similarity index 100% rename from clients/webassembly/src/encoded_payload_helper.rs rename to wasm/client/src/encoded_payload_helper.rs diff --git a/wasm/client/src/error.rs b/wasm/client/src/error.rs new file mode 100644 index 0000000000..0a01c97867 --- /dev/null +++ b/wasm/client/src/error.rs @@ -0,0 +1,51 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use js_sys::Promise; +use thiserror::Error; +use wasm_client_core::error::WasmCoreError; +use wasm_client_core::topology::WasmTopologyError; +use wasm_client_core::ClientCoreError; +use wasm_utils::wasm_error; + +#[cfg(feature = "node-tester")] +use nym_node_tester_utils::error::NetworkTestingError; + +#[derive(Debug, Error)] +pub enum WasmClientError { + #[error(transparent)] + CoreError { + #[from] + source: WasmCoreError, + }, + + #[error("failed to parse mix config options: {source}")] + MalformedConfigOptions { + #[from] + source: serde_wasm_bindgen::Error, + }, + + #[error("provided topology was malformed: {source}")] + InvalidTopology { + #[from] + source: WasmTopologyError, + }, + + #[cfg(feature = "node-tester")] + #[error("failed to test the node: {source}")] + NodeTestingFailure { + #[from] + source: NetworkTestingError, + }, +} + +// I dislike this so much - there must be a better way. +impl From for WasmClientError { + fn from(value: ClientCoreError) -> Self { + WasmClientError::CoreError { + source: WasmCoreError::BaseClientError { source: value }, + } + } +} + +wasm_error!(WasmClientError); diff --git a/clients/webassembly/src/client/helpers.rs b/wasm/client/src/helpers.rs similarity index 74% rename from clients/webassembly/src/client/helpers.rs rename to wasm/client/src/helpers.rs index 7d5373853b..c4c234c880 100644 --- a/clients/webassembly/src/client/helpers.rs +++ b/wasm/client/src/helpers.rs @@ -1,20 +1,28 @@ // Copyright 2022-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::error::WasmClientError; -use crate::tester::helpers::WasmTestMessageExt; -use crate::tester::{NodeTestMessage, DEFAULT_TEST_PACKETS}; -use crate::topology::WasmNymTopology; use js_sys::Promise; -use nym_client_core::client::base_client::{ClientInput, ClientState}; -use nym_client_core::client::inbound_messages::InputMessage; -use nym_topology::{MixLayer, NymTopology}; use std::sync::Arc; -use wasm_bindgen::prelude::*; use wasm_bindgen::JsValue; use wasm_bindgen_futures::future_to_promise; -use wasm_utils::{console_log, simple_js_error}; +use wasm_client_core::client::base_client::{ClientInput, ClientState}; +use wasm_client_core::client::inbound_messages::InputMessage; +use wasm_client_core::error::WasmCoreError; +use wasm_client_core::topology::WasmNymTopology; +use wasm_client_core::{MixLayer, NymTopology}; +use wasm_utils::error::simple_js_error; +use wasm_utils::{check_promise_result, console_log}; +#[cfg(feature = "node-tester")] +use nym_node_tester_wasm::types::{NodeTestMessage, WasmTestMessageExt}; + +#[cfg(feature = "node-tester")] +use wasm_bindgen::prelude::wasm_bindgen; + +#[cfg(feature = "node-tester")] +pub(crate) const DEFAULT_TEST_PACKETS: u32 = 20; + +#[cfg(feature = "node-tester")] #[wasm_bindgen] pub struct NymClientTestRequest { // serialized NodeTestMessage @@ -25,6 +33,7 @@ pub struct NymClientTestRequest { pub(crate) testable_topology: NymTopology, } +#[cfg(feature = "node-tester")] #[wasm_bindgen] impl NymClientTestRequest { pub fn injectable_topology(&self) -> WasmNymTopology { @@ -76,7 +85,10 @@ pub(crate) trait WasmTopologyExt { /// Checks whether the provided node exists in the known network topology and if so, returns its layer. fn check_for_mixnode_existence(&self, mixnode_identity: String) -> Promise; +} +#[cfg(feature = "node-tester")] +pub(crate) trait WasmTopologyTestExt { /// Creates a `NymClientTestRequest` with a variant of `this` topology where the target node is the only one on its layer. fn mix_test_request( &self, @@ -88,9 +100,10 @@ pub(crate) trait WasmTopologyExt { impl WasmTopologyExt for Arc { fn change_hardcoded_topology(&self, topology: WasmNymTopology) -> Promise { + let nym_topology: NymTopology = check_promise_result!(topology.try_into()); + let this = Arc::clone(self); future_to_promise(async move { - let nym_topology: NymTopology = topology.into(); console_log!("changing topology to {nym_topology:?}"); this.topology_accessor .manually_change_topology(nym_topology) @@ -103,8 +116,11 @@ impl WasmTopologyExt for Arc { let this = Arc::clone(self); future_to_promise(async move { match this.topology_accessor.current_topology().await { - Some(topology) => Ok(JsValue::from(WasmNymTopology::from(topology))), - None => Err(WasmClientError::UnavailableNetworkTopology.into()), + Some(topology) => Ok(serde_wasm_bindgen::to_value(&WasmNymTopology::from( + topology, + )) + .expect("WasmNymTopology failed serialization")), + None => Err(WasmCoreError::UnavailableNetworkTopology.into()), } }) } @@ -114,16 +130,19 @@ impl WasmTopologyExt for Arc { let this = Arc::clone(self); future_to_promise(async move { let Some(current_topology) = this.topology_accessor.current_topology().await else { - return Err(WasmClientError::UnavailableNetworkTopology.into()); + return Err(WasmCoreError::UnavailableNetworkTopology.into()); }; match current_topology.find_mix_by_identity(&mixnode_identity) { - None => Err(WasmClientError::NonExistentMixnode { mixnode_identity }.into()), + None => Err(WasmCoreError::NonExistentMixnode { mixnode_identity }.into()), Some(node) => Ok(JsValue::from(MixLayer::from(node.layer))), } }) } +} +#[cfg(feature = "node-tester")] +impl WasmTopologyTestExt for Arc { fn mix_test_request( &self, test_id: u32, @@ -135,16 +154,16 @@ impl WasmTopologyExt for Arc { let this = Arc::clone(self); future_to_promise(async move { let Some(current_topology) = this.topology_accessor.current_topology().await else { - return Err(WasmClientError::UnavailableNetworkTopology.into()); + return Err(WasmCoreError::UnavailableNetworkTopology.into()); }; let Some(mix) = current_topology.find_mix_by_identity(&mixnode_identity) else { - return Err(WasmClientError::NonExistentMixnode { mixnode_identity }.into()); + return Err(WasmCoreError::NonExistentMixnode { mixnode_identity }.into()); }; let ext = WasmTestMessageExt::new(test_id); let test_msgs = NodeTestMessage::mix_plaintexts(mix, num_test_packets, ext) - .map_err(WasmClientError::from)?; + .map_err(crate::error::WasmClientError::from)?; let mut updated = current_topology.clone(); updated.set_mixes_in_layer(mix.layer.into(), vec![mix.to_owned()]); diff --git a/wasm/client/src/lib.rs b/wasm/client/src/lib.rs new file mode 100644 index 0000000000..aed1179aaa --- /dev/null +++ b/wasm/client/src/lib.rs @@ -0,0 +1,18 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +#[cfg(target_arch = "wasm32")] +pub mod client; +#[cfg(target_arch = "wasm32")] +pub mod config; +#[cfg(target_arch = "wasm32")] +pub mod encoded_payload_helper; +#[cfg(target_arch = "wasm32")] +pub mod error; +#[cfg(target_arch = "wasm32")] +mod helpers; +#[cfg(target_arch = "wasm32")] +mod response_pusher; + +#[cfg(target_arch = "wasm32")] +pub use wasm_client_core::set_panic_hook; diff --git a/clients/webassembly/src/client/response_pusher.rs b/wasm/client/src/response_pusher.rs similarity index 87% rename from clients/webassembly/src/client/response_pusher.rs rename to wasm/client/src/response_pusher.rs index 642fb951e7..42d88a86c8 100644 --- a/clients/webassembly/src/client/response_pusher.rs +++ b/wasm/client/src/response_pusher.rs @@ -4,12 +4,12 @@ use futures::channel::mpsc; use futures::StreamExt; use js_sys::Uint8Array; -use nym_client_core::client::base_client::ClientOutput; -use nym_client_core::client::received_buffer::{ - ReceivedBufferMessage, ReconstructedMessagesReceiver, -}; use wasm_bindgen::JsValue; use wasm_bindgen_futures::spawn_local; +use wasm_client_core::client::base_client::ClientOutput; +use wasm_client_core::client::received_buffer::{ + ReceivedBufferMessage, ReconstructedMessagesReceiver, +}; use wasm_utils::console_error; pub(crate) struct ResponsePusher { @@ -18,7 +18,11 @@ pub(crate) struct ResponsePusher { } impl ResponsePusher { - pub(crate) fn new(client_output: ClientOutput, on_message: js_sys::Function) -> Self { + pub(crate) fn new( + client_output: ClientOutput, + on_message: js_sys::Function, + // on_mix_fetch_message: js_sys::Function, + ) -> Self { // register our output let (reconstructed_sender, reconstructed_receiver) = mpsc::unbounded(); diff --git a/wasm/full-nym-wasm/.cargo/config.toml b/wasm/full-nym-wasm/.cargo/config.toml new file mode 100644 index 0000000000..bdbe517658 --- /dev/null +++ b/wasm/full-nym-wasm/.cargo/config.toml @@ -0,0 +1,3 @@ +[build] +target = "wasm32-unknown-unknown" +target_arch = "wasm32" diff --git a/wasm/full-nym-wasm/Cargo.toml b/wasm/full-nym-wasm/Cargo.toml new file mode 100644 index 0000000000..4570ba5a04 --- /dev/null +++ b/wasm/full-nym-wasm/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "nym-wasm-sdk" +authors = ["Jedrzej Stuczynski "] +version = "1.2.0-rc.2" +edition = "2021" +keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"] +license = "Apache-2.0" +repository = "https://github.com/nymtech/nym" +rust-version = "1.56" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +nym-client-wasm = { path = "../client", optional = true } +nym-node-tester-wasm = { path = "../node-tester", optional = true } +mix-fetch-wasm = { path = "../mix-fetch", optional = true } + +[features] +default = ["client", "node-tester"] +client = ["nym-client-wasm"] +node-tester = ["nym-node-tester-wasm"] +mix-fetch = ["mix-fetch-wasm"] + +[package.metadata.wasm-pack.profile.release] +wasm-opt = false + +[profile.release] +lto = true +opt-level = 'z' diff --git a/wasm/full-nym-wasm/Makefile b/wasm/full-nym-wasm/Makefile new file mode 100644 index 0000000000..686af08cc4 --- /dev/null +++ b/wasm/full-nym-wasm/Makefile @@ -0,0 +1,3 @@ +build-full: + wasm-pack build --all-features --scope nymproject --target web --out-dir ../../dist/wasm/full-nym-wasm + wasm-opt -Oz -o ../../dist/wasm/full-nym-wasm/nym_wasm_sdk_bg.wasm ../../dist/wasm/full-nym-wasm/nym_wasm_sdk_bg.wasm diff --git a/wasm/full-nym-wasm/src/lib.rs b/wasm/full-nym-wasm/src/lib.rs new file mode 100644 index 0000000000..8f2009bcbf --- /dev/null +++ b/wasm/full-nym-wasm/src/lib.rs @@ -0,0 +1,11 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +#[cfg(all(target_arch = "wasm32", feature = "client"))] +pub use nym_client_wasm as client; + +#[cfg(all(target_arch = "wasm32", feature = "node-tester"))] +pub use nym_node_tester_wasm as node_tester; + +#[cfg(all(target_arch = "wasm32", feature = "mix-fetch"))] +pub use mix_fetch_wasm as mix_fetch; diff --git a/wasm/mix-fetch/.cargo/config.toml b/wasm/mix-fetch/.cargo/config.toml new file mode 100644 index 0000000000..bdbe517658 --- /dev/null +++ b/wasm/mix-fetch/.cargo/config.toml @@ -0,0 +1,3 @@ +[build] +target = "wasm32-unknown-unknown" +target_arch = "wasm32" diff --git a/wasm/mix-fetch/Cargo.toml b/wasm/mix-fetch/Cargo.toml new file mode 100644 index 0000000000..96f3526363 --- /dev/null +++ b/wasm/mix-fetch/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "mix-fetch-wasm" +authors = ["Jedrzej Stuczynski "] +version = "1.2.0-rc.2" +edition = "2021" +keywords = ["nym", "fetch", "wasm", "webassembly", "privacy"] +license = "Apache-2.0" +repository = "https://github.com/nymtech/nym" +rust-version = "1.70" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +futures = { workspace = true } +js-sys = { workspace = true } +rand = { version = "0.7.3", features = ["wasm-bindgen"] } +reqwest = { workspace = true, default-features = false } +serde = { workspace = true, features = ["derive"] } +serde-wasm-bindgen = { workspace = true } +tokio = { workspace = true, features = ["sync"] } +url = { workspace = true } +wasm-bindgen = { workspace = true } +wasm-bindgen-futures = { workspace = true } +thiserror = { workspace = true } +tsify = { workspace = true, features = ["js"] } + +nym-socks5-requests = { path = "../../common/socks5/requests" } +nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" } +nym-service-providers-common = { path = "../../service-providers/common" } +wasm-client-core = { path = "../../common/wasm/client-core" } +wasm-utils = { path = "../../common/wasm/utils" } + +[package.metadata.wasm-pack.profile.release] +wasm-opt = false + +[profile.release] +lto = true +opt-level = 'z' diff --git a/wasm/mix-fetch/Makefile b/wasm/mix-fetch/Makefile new file mode 100644 index 0000000000..776d6d35bb --- /dev/null +++ b/wasm/mix-fetch/Makefile @@ -0,0 +1,39 @@ +build: build-go-opt build-rust build-package-json + +check-fmt: check-fmt-go check-fmt-rust + +build-go: + $(MAKE) -C go-mix-conn build-go + +build-go-opt: + $(MAKE) -C go-mix-conn build-go-opt + +build-rust: + wasm-pack build --scope nymproject --target web --out-dir ../../dist/wasm/mix-fetch + wasm-opt -Oz -o ../../dist/wasm/mix-fetch/mix_fetch_wasm_bg.wasm ../../dist/wasm/mix-fetch/mix_fetch_wasm_bg.wasm + +build-package-json: + node build.mjs + +check-fmt-go: + $(MAKE) -C go-mix-conn check-fmt + +check-fmt-rust: + cargo fmt --check + cargo clippy --target wasm32-unknown-unknown -- -Dwarnings + +###### NODEJS + +build-rust-node: + wasm-pack build --scope nymproject --target nodejs --out-dir ../../dist/node/wasm/mix-fetch + wasm-opt -Oz -o ../../dist/node/wasm/mix-fetch/mix_fetch_wasm_bg.wasm ../../dist/node/wasm/mix-fetch/mix_fetch_wasm_bg.wasm + +build-package-json-node: + node build-node.mjs + +copy-go-conn: + mkdir -p ../../dist/node/wasm/mix-fetch + cp ../../dist/wasm/mix-fetch/go_conn.wasm ../../dist/node/wasm/mix-fetch/go_conn.wasm + cp ../../dist/wasm/mix-fetch/wasm_exec.js ../../dist/node/wasm/mix-fetch/wasm_exec.js + +build-node: build-go-opt copy-go-conn build-rust-node build-package-json-node \ No newline at end of file diff --git a/wasm/mix-fetch/build-node.mjs b/wasm/mix-fetch/build-node.mjs new file mode 100644 index 0000000000..3782ce7941 --- /dev/null +++ b/wasm/mix-fetch/build-node.mjs @@ -0,0 +1,12 @@ +import fs from 'fs'; + +const packageJson = JSON.parse(fs.readFileSync('../../dist/node/wasm/mix-fetch/package.json').toString()); + +if (!packageJson.files.includes('go_conn.wasm')) { + packageJson.files.push('go_conn.wasm'); +} +if (!packageJson.files.includes('wasm_exec.js')) { + packageJson.files.push('wasm_exec.js'); +} + +fs.writeFileSync('../../dist/node/wasm/mix-fetch/package.json', JSON.stringify(packageJson, null, 2)); \ No newline at end of file diff --git a/wasm/mix-fetch/build.mjs b/wasm/mix-fetch/build.mjs new file mode 100644 index 0000000000..5626beb736 --- /dev/null +++ b/wasm/mix-fetch/build.mjs @@ -0,0 +1,12 @@ +import fs from 'fs'; + +const packageJson = JSON.parse(fs.readFileSync('../../dist/wasm/mix-fetch/package.json').toString()); + +if (!packageJson.files.includes('go_conn.wasm')) { + packageJson.files.push('go_conn.wasm'); +} +if (!packageJson.files.includes('wasm_exec.js')) { + packageJson.files.push('wasm_exec.js'); +} + +fs.writeFileSync('../../dist/wasm/mix-fetch/package.json', JSON.stringify(packageJson, null, 2)); \ No newline at end of file diff --git a/wasm/mix-fetch/go-mix-conn/.gitignore b/wasm/mix-fetch/go-mix-conn/.gitignore new file mode 100644 index 0000000000..ef21965b69 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/.gitignore @@ -0,0 +1,2 @@ +build/wasm_exec.js +build/main.wasm \ No newline at end of file diff --git a/wasm/mix-fetch/go-mix-conn/Makefile b/wasm/mix-fetch/go-mix-conn/Makefile new file mode 100644 index 0000000000..462cb68126 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/Makefile @@ -0,0 +1,34 @@ +ifndef $(GOROOT) + GOROOT=$(shell go env GOROOT) + export GOROOT +endif + + +ifndef $(TINYGOROOT) + TINYGOROOT=$(shell tinygo env TINYGOROOT) + export TINYGOROOT +endif + +build-go: + GOOS=js GOARCH=wasm go build -o ../../../dist/wasm/mix-fetch/go_conn.wasm ./cmd/wasm + cp "$(GOROOT)/misc/wasm/wasm_exec.js" ../../../dist/wasm/mix-fetch + + +build-go-opt: +# use the -s and -w linker flags to strip the debugging information + GOOS=js GOARCH=wasm go build -ldflags="-s -w" -o ../../../dist/wasm/mix-fetch/go_conn.wasm ./cmd/wasm + cp "$(GOROOT)/misc/wasm/wasm_exec.js" ../../../dist/wasm/mix-fetch + +# run wasm-opt to gain few more kb + wasm-opt --enable-bulk-memory -Oz ../../../dist/wasm/mix-fetch/go_conn.wasm -o ../../../dist/wasm/mix-fetch/go_conn.wasm +# finally compress it (... or not?) + +build-tinygo: +# the default stack size of 16kib is insufficient +# note: it seems to leak memory : ( +# ref: https://github.com/tinygo-org/tinygo/issues/1140 +# HOWEVER. it could be severely reduced via: https://github.com/tinygo-org/tinygo/issues/1140#issuecomment-718145455 + tinygo build -o ../../../dist/wasm/mix-fetch/go_conn.wasm -stack-size "32kb" ./cmd/wasm && cp "$(TINYGOROOT)/targets/wasm_exec.js" ../../../dist/wasm/mix-fetch + +check-fmt: + test -z $(gofmt -l .) \ No newline at end of file diff --git a/wasm/mix-fetch/go-mix-conn/cmd/wasm/main.go b/wasm/mix-fetch/go-mix-conn/cmd/wasm/main.go new file mode 100644 index 0000000000..cdd2638cf1 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/cmd/wasm/main.go @@ -0,0 +1,31 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +//go:build js && wasm + +package main + +import ( + "go-mix-conn/internal/bridge/go_bridge" + "go-mix-conn/internal/state" +) + +var done chan struct{} + +func init() { + println("[go init]: go module init") + + done = make(chan struct{}) + state.InitialiseGlobalState() + + println("[go init]: go module init finished") +} + +func main() { + println("[go main]: go module loaded") + + go_bridge.InitialiseGoBridge() + <-done + + println("[go main]: go module finished") +} diff --git a/wasm/mix-fetch/go-mix-conn/go.mod b/wasm/mix-fetch/go-mix-conn/go.mod new file mode 100644 index 0000000000..ff161559bb --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/go.mod @@ -0,0 +1,7 @@ +module go-mix-conn + +go 1.20 + +require golang.org/x/net v0.11.0 + +require golang.org/x/text v0.10.0 // indirect diff --git a/wasm/mix-fetch/go-mix-conn/go.sum b/wasm/mix-fetch/go-mix-conn/go.sum new file mode 100644 index 0000000000..6ea647559f --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/go.sum @@ -0,0 +1,4 @@ +golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= +golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= +golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= diff --git a/wasm/mix-fetch/go-mix-conn/internal/bridge/go_bridge/go_bridge.go b/wasm/mix-fetch/go-mix-conn/internal/bridge/go_bridge/go_bridge.go new file mode 100644 index 0000000000..e44c8cb9d7 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/bridge/go_bridge/go_bridge.go @@ -0,0 +1,153 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package go_bridge + +import ( + "errors" + "fmt" + "go-mix-conn/internal/bridge/rust_bridge" + "go-mix-conn/internal/helpers" + "go-mix-conn/internal/jstypes" + "go-mix-conn/internal/jstypes/conv" + "go-mix-conn/internal/log" + "go-mix-conn/internal/mixfetch" + "syscall/js" + "time" +) + +const ( + // methods exposed by go to rust + goRustBridgeName = "__go_rs_bridge__" +) + +func createGoBridgeObject() js.Value { + js.Global().Set(goRustBridgeName, jstypes.Object.New()) + goBridgeRoot := js.Global().Get(goRustBridgeName) + return goBridgeRoot +} + +func InitialiseGoBridge() { + goBridgeRoot := createGoBridgeObject() + + // user facing methods + js.Global().Set("mixFetch", jstypes.AsyncFunc(mixFetch)) + js.Global().Set("goWasmSetLogging", js.FuncOf(setLoggingLevel)) + + // rust facing methods (don't expose them to the root) + goBridgeRoot.Set("goWasmSetMixFetchRequestTimeout", js.FuncOf(changeRequestTimeout)) + goBridgeRoot.Set("goWasmInjectServerData", js.FuncOf(injectServerData)) + goBridgeRoot.Set("goWasmCloseRemoteSocket", js.FuncOf(closeRemoteSocket)) + goBridgeRoot.Set("goWasmInjectConnError", js.FuncOf(injectConnError)) +} + +func setLoggingLevel(_ js.Value, args []js.Value) any { + if len(args) == 0 { + return errors.New("no arguments passed for `setLoggingLevel`") + } + + if args[0].Type() != js.TypeString { + return errors.New("the provided logging level is not a string") + } + log.SetLoggingLevel(args[0].String()) + return nil +} + +func mixFetch(_ js.Value, args []js.Value) (any, error) { + if !rust_bridge.RsIsInitialised() { + return nil, errors.New("mix fetch hasn't been initialised") + } + + if len(args) == 0 { + return nil, errors.New("no arguments passed for `mixfetch`") + } + + requestConstructor := jstypes.Request + + jsRequest := js.Null() + unsafeCors := false + // that's bit weird. can't use the spread operator + if len(args) == 1 { + jsRequest = requestConstructor.New(args[0]) + } + if len(args) == 2 { + if !args[1].IsUndefined() && !args[1].IsNull() { + // check for 'MODE_UNSAFE_IGNORE_CORS' + if args[1].Get("mode").String() == jstypes.ModeUnsafeIgnoreCors { + unsafeCors = true + // we need to delete that prop as technically it holds an invalid value to construct `Request` + args[1].Delete("mode") + } + } + + jsRequest = requestConstructor.New(args[0], args[1]) + } + + goRequest, err := conv.ParseJSRequest(jsRequest, unsafeCors) + if err != nil { + return nil, err + } + + return mixfetch.MixFetch(goRequest) +} + +func injectServerData(_ js.Value, args []js.Value) any { + if len(args) != 2 { + return errors.New(fmt.Sprintf("received invalid number of arguments. Got %d but expected 2", len(args))) + } + requestId, err := helpers.ParseRequestId(args[0]) + if err != nil { + return err + } + data, err := helpers.IntoGoBytes(args[1]) + if err != nil { + return err + } + + return mixfetch.InjectServerData(requestId, data) +} + +func injectConnError(_ js.Value, args []js.Value) any { + if len(args) != 2 { + return errors.New(fmt.Sprintf("received invalid number of arguments. Got %d but expected 2", len(args))) + } + + requestId, err := helpers.ParseRequestId(args[0]) + if err != nil { + return err + } + + if args[1].Type() != js.TypeString { + return errors.New("provided error message is not a string") + } + errMsg := args[1].String() + remoteErr := errors.New(errMsg) + + return mixfetch.InjectConnError(requestId, remoteErr) +} + +func closeRemoteSocket(_ js.Value, args []js.Value) any { + if len(args) != 1 { + return errors.New(fmt.Sprintf("received invalid number of arguments. Got %d but expected 1", len(args))) + } + requestId, err := helpers.ParseRequestId(args[0]) + if err != nil { + return err + } + + return mixfetch.CloseRemoteSocket(requestId) +} + +func changeRequestTimeout(_ js.Value, args []js.Value) any { + if len(args) != 1 { + return errors.New(fmt.Sprintf("received invalid number of arguments. Got %d but expected 1", len(args))) + } + + if args[0].Type() != js.TypeNumber { + return errors.New("the provided timeout is not a number") + } + timeoutMs := args[0].Int() + timeout := time.Millisecond * time.Duration(timeoutMs) + + return mixfetch.ChangeRequestTimeout(timeout) +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/bridge/rust_bridge/rust_bridge.go b/wasm/mix-fetch/go-mix-conn/internal/bridge/rust_bridge/rust_bridge.go new file mode 100644 index 0000000000..3c4273eb1a --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/bridge/rust_bridge/rust_bridge.go @@ -0,0 +1,80 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +// it's not a bridge per se, but it makes it easier to keep track of what rust endpoints we're calling from go + +package rust_bridge + +import ( + "go-mix-conn/internal/helpers" + "go-mix-conn/internal/jstypes" + "go-mix-conn/internal/log" + "go-mix-conn/internal/types" + "strconv" + "syscall/js" +) + +const ( + // methods exposed by rust to go + rustGoBridgeName = "__rs_go_bridge__" +) + +func rsBridge() js.Value { + return js.Global().Get(rustGoBridgeName) +} + +func RsSendClientData(requestId types.RequestId, data []byte) error { + log.Debug("calling rust send_client_data") + + rawRequestId := strconv.FormatUint(requestId, 10) + jsBytes := helpers.IntoJsBytes(data) + + sendPromise := rsBridge().Call("send_client_data", rawRequestId, jsBytes) + _, err := jstypes.Await(sendPromise) + if err != nil { + panic("todo: extract error message") + } + return nil +} + +func RsStartNewMixnetRequest(addr string) (types.RequestId, error) { + log.Debug("calling rust start_new_mixnet_connection") + + requestPromise := rsBridge().Call("start_new_mixnet_connection", addr) + rawRequestId, errRes := jstypes.Await(requestPromise) + if errRes != nil { + panic("todo: extract error message") + } + + if len(rawRequestId) != 1 { + panic("todo: handle error here") + } + + requestId, err := helpers.ParseRequestId(rawRequestId[0]) + if err != nil { + return 0, err + } + + log.Debug("started request has id %d", requestId) + + return requestId, err +} + +func RsIsInitialised() bool { + log.Debug("calling rust mix_fetch_initialised") + + return rsBridge().Call("mix_fetch_initialised").Bool() +} + +func RsFinishMixnetConnection(requestId types.RequestId) error { + log.Debug("calling rust finish_mixnet_connection") + + rawRequestId := strconv.FormatUint(requestId, 10) + + finishPromise := rsBridge().Call("finish_mixnet_connection", rawRequestId) + _, err := jstypes.Await(finishPromise) + if err != nil { + panic("todo: extract error message") + } + return nil +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/external/roundtrip_js.go b/wasm/mix-fetch/go-mix-conn/internal/external/roundtrip_js.go new file mode 100644 index 0000000000..547fdc4b42 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/external/roundtrip_js.go @@ -0,0 +1,158 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file: +// https://github.com/golang/go/blob/release-branch.go1.20/LICENSE + +//go:build js && wasm + +package external + +import ( + "errors" + "io" + "syscall/js" +) + +var errClosed = errors.New("net/http: reader is closed") + +// StreamReader implements an io.ReadCloser wrapper for ReadableStream. +// See https://fetch.spec.whatwg.org/#readablestream for more information. +// SOURCE: https://github.com/golang/go/blob/release-branch.go1.20/src/net/http/roundtrip_js.go +type StreamReader struct { + pending []byte + stream js.Value + err error // sticky read error +} + +func NewStreamReader(stream js.Value) *StreamReader { + return &StreamReader{ + stream: stream, + } +} + +// SOURCE: https://github.com/golang/go/blob/release-branch.go1.20/src/net/http/roundtrip_js.go +func (r *StreamReader) Read(p []byte) (n int, err error) { + if r.err != nil { + return 0, r.err + } + if len(r.pending) == 0 { + var ( + bCh = make(chan []byte, 1) + errCh = make(chan error, 1) + ) + success := js.FuncOf(func(this js.Value, args []js.Value) any { + result := args[0] + if result.Get("done").Bool() { + errCh <- io.EOF + return nil + } + value := make([]byte, result.Get("value").Get("byteLength").Int()) + js.CopyBytesToGo(value, result.Get("value")) + bCh <- value + return nil + }) + defer success.Release() + failure := js.FuncOf(func(this js.Value, args []js.Value) any { + // Assumes it's a TypeError. See + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError + // for more information on this type. See + // https://streams.spec.whatwg.org/#byob-reader-read for the spec on + // the read method. + errCh <- errors.New(args[0].Get("message").String()) + return nil + }) + defer failure.Release() + r.stream.Call("read").Call("then", success, failure) + select { + case b := <-bCh: + r.pending = b + case err := <-errCh: + r.err = err + return 0, err + } + } + n = copy(p, r.pending) + r.pending = r.pending[n:] + return n, nil +} + +// SOURCE: https://github.com/golang/go/blob/release-branch.go1.20/src/net/http/roundtrip_js.go +func (r *StreamReader) Close() error { + // This ignores any error returned from cancel method. So far, I did not encounter any concrete + // situation where reporting the error is meaningful. Most users ignore error from resp.Body.Close(). + // If there's a need to report error here, it can be implemented and tested when that need comes up. + r.stream.Call("cancel") + if r.err == nil { + r.err = errClosed + } + return nil +} + +// ArrayReader implements an io.ReadCloser wrapper for ArrayBuffer. +// https://developer.mozilla.org/en-US/docs/Web/API/Body/arrayBuffer. +// SOURCE: https://github.com/golang/go/blob/release-branch.go1.20/src/net/http/roundtrip_js.go +type ArrayReader struct { + arrayPromise js.Value + pending []byte + read bool + err error // sticky read error +} + +func NewArrayReader(arrayPromise js.Value) *ArrayReader { + return &ArrayReader{ + arrayPromise: arrayPromise, + } +} + +// SOURCE: https://github.com/golang/go/blob/release-branch.go1.20/src/net/http/roundtrip_js.go +func (r *ArrayReader) Read(p []byte) (n int, err error) { + if r.err != nil { + return 0, r.err + } + if !r.read { + r.read = true + var ( + bCh = make(chan []byte, 1) + errCh = make(chan error, 1) + ) + success := js.FuncOf(func(this js.Value, args []js.Value) any { + // Wrap the input ArrayBuffer with a Uint8Array + uint8arrayWrapper := js.Global().Get("Uint8Array").New(args[0]) + value := make([]byte, uint8arrayWrapper.Get("byteLength").Int()) + js.CopyBytesToGo(value, uint8arrayWrapper) + bCh <- value + return nil + }) + defer success.Release() + failure := js.FuncOf(func(this js.Value, args []js.Value) any { + // Assumes it's a TypeError. See + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError + // for more information on this type. + // See https://fetch.spec.whatwg.org/#concept-body-consume-body for reasons this might error. + errCh <- errors.New(args[0].Get("message").String()) + return nil + }) + defer failure.Release() + r.arrayPromise.Call("then", success, failure) + select { + case b := <-bCh: + r.pending = b + case err := <-errCh: + return 0, err + } + } + if len(r.pending) == 0 { + return 0, io.EOF + } + n = copy(p, r.pending) + r.pending = r.pending[n:] + return n, nil +} + +// SOURCE: https://github.com/golang/go/blob/release-branch.go1.20/src/net/http/roundtrip_js.go +func (r *ArrayReader) Close() error { + if r.err == nil { + r.err = errClosed + } + return nil +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/external/set.go b/wasm/mix-fetch/go-mix-conn/internal/external/set.go new file mode 100644 index 0000000000..d2c3086bab --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/external/set.go @@ -0,0 +1,26 @@ +package external + +// SOURCE: https://github.com/jub0bs/fcors/blob/main/internal/util/set.go + +// A Set represents a mathematical set whose elements have type E. +type Set[E comparable] map[E]struct{} + +// NewSet returns a Set that contains all of es (and no other elements). +func NewSet[E comparable](es ...E) Set[E] { + set := make(Set[E], len(es)) + for _, e := range es { + set.Add(e) + } + return set +} + +// Add adds e to s. +func (s Set[E]) Add(e E) { + s[e] = struct{}{} +} + +// Contains returns true if e is an element of s, and false otherwise. +func (s Set[E]) Contains(e E) bool { + _, found := s[e] + return found +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/helpers/helpers.go b/wasm/mix-fetch/go-mix-conn/internal/helpers/helpers.go new file mode 100644 index 0000000000..5e3ef3ebd3 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/helpers/helpers.go @@ -0,0 +1,121 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package helpers + +import ( + "errors" + "fmt" + "go-mix-conn/internal/external" + "golang.org/x/net/http/httpguts" + "sort" + "strconv" + "strings" + "syscall/js" +) + +func ParseRequestId(raw js.Value) (uint64, error) { + if raw.Type() != js.TypeString { + return 0, errors.New("the received raw request id was not a string") + } + + return strconv.ParseUint(raw.String(), 10, 64) +} + +func IntoGoBytes(raw js.Value) ([]byte, error) { + if raw.Type() != js.TypeObject { + return nil, errors.New("the received 'bytes' are not an object") + } + lenProp := raw.Get("length") + if lenProp.Type() != js.TypeNumber { + return nil, errors.New("the received 'bytes' object does not have a numerical 'length' property") + } + n := lenProp.Int() + bytes := make([]byte, n) + + // TODO: somehow check that the object is an Uint8Array or Uint8ClampedArray + copied := js.CopyBytesToGo(bytes, raw) + if copied != n { + // I don't see how this could ever be reached, thus panic + panic("somehow copied fewer bytes from JavaScript into Go than what we specified as our buffer") + } + + return bytes, nil +} + +func IntoJsBytes(raw []byte) js.Value { + // "data" is a byte slice, so we need to convert it to a JS Uint8Array object + arrayConstructor := js.Global().Get("Uint8Array") + jsBytes := arrayConstructor.New(len(raw)) + js.CopyBytesToJS(jsBytes, raw) + return jsBytes +} + +func GetStringProperty(obj *js.Value, name string) (string, error) { + val := obj.Get(name) + if val.Type() != js.TypeString { + return "", errors.New(fmt.Sprintf("the property %s is not a string", name)) + } + return val.String(), nil +} + +func IsToken(raw string) bool { + if len(raw) == 0 { + return false + } + for _, b := range []byte(raw) { + if !httpguts.IsTokenRune(rune(b)) { + return false + } + } + return true +} + +func ByteLowercase(s string) string { + return strings.Map(byteLowercaseOne, s) +} + +func byteLowercaseOne(asciiRune rune) rune { + const toLower = 'a' - 'A' + if 'A' <= asciiRune && asciiRune <= 'Z' { + return asciiRune + toLower + } + return asciiRune +} + +func SortedByteLowercase(s []string) []string { + lowercase := make([]string, len(s)) + for i := 0; i < len(s); i++ { + lowercase[i] = ByteLowercase(s[i]) + } + sort.Strings(lowercase) + return lowercase +} + +func Contains(s []string, str string) bool { + for _, v := range s { + if v == str { + return true + } + } + + return false +} + +func Unique(s []string) []string { + uniqueSet := external.NewSet(s...) + + uniqueSlice := make([]string, len(uniqueSet)) + for v := range uniqueSet { + uniqueSlice = append(uniqueSlice, v) + } + return uniqueSlice +} + +func IntoAnySlice(v []js.Value) []any { + s := make([]any, len(v)) + for i, x := range v { + s[i] = x + } + return s +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/jstypes/async.go b/wasm/mix-fetch/go-mix-conn/internal/jstypes/async.go new file mode 100644 index 0000000000..3b8bcfc4be --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/jstypes/async.go @@ -0,0 +1,67 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package jstypes + +import ( + "fmt" + "syscall/js" +) + +type jsFn func(this js.Value, args []js.Value) (any, error) + +// AsyncFunc converts a Go-JS function into a Promise +func AsyncFunc(innerFunc jsFn) js.Func { + return js.FuncOf(func(this js.Value, args []js.Value) any { + handler := js.FuncOf(func(_ js.Value, promFn []js.Value) any { + resolve, reject := promFn[0], promFn[1] + + go func() { + defer func() { + if r := recover(); r != nil { + reject.Invoke(Error.New(fmt.Sprint("panic:", r))) + } + }() + + res, err := innerFunc(this, args) + if err != nil { + reject.Invoke(Error.New(err.Error())) + } else { + resolve.Invoke(res) + } + }() + + return nil + }) + + return Promise.New(handler) + }) +} + +// https://stackoverflow.com/a/68427221 +func Await(awaitable js.Value) ([]js.Value, []js.Value) { + then := make(chan []js.Value) + defer close(then) + thenFunc := js.FuncOf(func(this js.Value, args []js.Value) any { + then <- args + return nil + }) + defer thenFunc.Release() + + catch := make(chan []js.Value) + defer close(catch) + catchFunc := js.FuncOf(func(this js.Value, args []js.Value) any { + catch <- args + return nil + }) + defer catchFunc.Release() + + awaitable.Call("then", thenFunc).Call("catch", catchFunc) + + select { + case result := <-then: + return result, nil + case err := <-catch: + return nil, err + } +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/jstypes/conv/request.go b/wasm/mix-fetch/go-mix-conn/internal/jstypes/conv/request.go new file mode 100644 index 0000000000..27621e83ae --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/jstypes/conv/request.go @@ -0,0 +1,414 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package conv + +import ( + "bytes" + "context" + "errors" + "fmt" + "go-mix-conn/internal/external" + "go-mix-conn/internal/helpers" + "go-mix-conn/internal/jstypes" + "go-mix-conn/internal/log" + "go-mix-conn/internal/types" + "io" + "net/http" + "net/url" + "syscall/js" +) + +const ( + fieldRequestMethod = "method" + fieldRequestUrl = "url" + fieldRequestBody = "body" + fieldRequestRedirect = "redirect" + fieldRequestMode = "mode" + fieldRequestCredentials = "credentials" + fieldRequestReferrer = "referrer" + fieldRequestReferrerPolicy = "referrerPolicy" + fieldRequestHeaders = "headers" + fieldRequestCache = "cache" + fieldRequestSignal = "signal" +) + +type ParsedRequest struct { + Request *http.Request + Options *types.RequestOptions +} + +// ParseJSRequest is a reverse of https://github.com/golang/go/blob/release-branch.go1.21/src/net/http/roundtrip_js.go#L91 +// https://developer.mozilla.org/en-US/docs/Web/API/request +// +// Preflight requests: status unknown +/* + Request attributes and their implementation status: + [✅] - supported + [⚠️] - partially supported (some features might be missing) + [❌] - unsupported + [❗] - not applicable / will not support + + [⚠️] body - the current streaming is a bit awkward + [❌] bodyUsed + [❗️] cache + [❌] credentials + [❌] destination + [⚠️] headers - not all headers are properly respected + [❌] integrity + [✅] method + [✅] mode + [✅️] redirect + [❌] referrer + [❌] referrerPolicy + [✅] signal + [✅] url +*/ +func ParseJSRequest(request js.Value, unsafeCors bool) (*ParsedRequest, error) { + // https://github.com/mozilla/gecko-dev/blob/d307d4d9f06dab6d16e963a4318e5e8ff4899141/dom/fetch/Fetch.cpp#L501 + // https://github.com/mozilla/gecko-dev/blob/d307d4d9f06dab6d16e963a4318e5e8ff4899141/dom/fetch/Request.cpp#L270 + + method, err := helpers.GetStringProperty(&request, fieldRequestMethod) + if err != nil { + return nil, err + } + + requestUrl, err := helpers.GetStringProperty(&request, fieldRequestUrl) + if err != nil { + return nil, err + } + + body, err := parseBody(&request) + if err != nil { + return nil, err + } + redirect, err := parseRedirect(&request) + if err != nil { + return nil, err + } + + mode, err := parseMode(&request, unsafeCors) + if err != nil { + return nil, err + } + + credentialsMode, err := parseCredentialsMode(&request) + if err != nil { + return nil, err + } + + referrer, err := parseReferrer(&request) + if err != nil { + return nil, err + } + + referrerPolicy, err := parseRefererPolicy(&request) + if err != nil { + return nil, err + } + + ctx, cancel := context.WithCancel(context.Background()) + if err := dealWithSignal(&request, cancel); err != nil { + return nil, err + } + + // A Request has an associated response tainting, which is "basic", "cors", or "opaque". + // Unless stated otherwise, it is "basic". + // Reference: https://fetch.spec.whatwg.org/#concept-request-response-tainting + responseTainting := jstypes.ResponseTaintingBasic + + options := types.RequestOptions{ + Redirect: redirect, + Mode: mode, + CredentialsMode: credentialsMode, + Referrer: referrer, + ReferrerPolicy: referrerPolicy, + ResponseTainting: responseTainting, + Method: method, + } + + jsHeaders := request.Get(fieldRequestHeaders) + headers, err := parseHeaders(jsHeaders, options, method) + if err != nil { + return nil, err + } + + checkUnsupportedAttributes(&request) + + req, err := http.NewRequestWithContext(ctx, method, requestUrl, body) + if err != nil { + return nil, err + } + req.Header = headers + + log.Debug("constructed Request: %+v", req) + log.Debug("using Options: %s", options) + + return &ParsedRequest{ + Request: req, + Options: &options, + }, nil +} + +func checkUnsupportedAttributes(request *js.Value) { + cache := request.Get(fieldRequestCache) + + if !cache.IsUndefined() { + log.Warn("\"%s\"' attribute is set on the Request - this is not supported by mixFetch", fieldRequestCache) + } + + // TODO: implement more of them +} + +func parseHeaders(headers js.Value, reqOpts types.RequestOptions, method string) (http.Header, error) { + goHeaders := http.Header{} + + if headers.Type() != js.TypeObject { + return nil, errors.New("the Request headers is not an object") + } + headersIter := headers.Call("entries") + + for { + next := headersIter.Call("next") + done := next.Get("done").Bool() + if done { + break + } + keyValue := next.Get("value") + if keyValue.Length() != 2 { + return nil, errors.New("one of the headers has invalid length") + } + key := keyValue.Index(0) + if key.Type() != js.TypeString { + return nil, errors.New("one of the header keys is not a string") + } + + value := keyValue.Index(1) + if value.Type() != js.TypeString { + return nil, errors.New("one of the header values is not a string") + } + ck := http.CanonicalHeaderKey(key.String()) + goHeaders[ck] = append(goHeaders[ck], value.String()) + } + + // add additional headers + + // 3.1.1 + origin := jstypes.Origin() + serializedOrigin := &origin + // Reference: https://fetch.spec.whatwg.org/#origin-header + // TODO: 3.1.2: check response tainting + // 3.1.3 + if method != "GET" && method != "HEAD" { + // 3.1.3.1 + if reqOpts.Mode != jstypes.ModeCors { + switch reqOpts.ReferrerPolicy { + case jstypes.ReferrerNoReferrer: + serializedOrigin = nil + case jstypes.ReferrerPolicyNoReferrerWhenDowngrade, jstypes.ReferrerPolicyStrictOrigin, jstypes.ReferrerPolicyStrictOriginWhenCrossOrigin: + panic("unimplemented Referrer policy") + case jstypes.ReferrerPolicySameOrigin: + panic("unimplemented Referrer policy") + } + } + // 3.1.3.2 + if serializedOrigin != nil { + goHeaders.Set(jstypes.HeaderOrigin, *serializedOrigin) + } + } + + return goHeaders, nil +} + +func parseBody(request *js.Value) (io.Reader, error) { + jsBody := request.Get(fieldRequestBody) + var bodyReader io.Reader + if !jsBody.IsUndefined() && !jsBody.IsNull() { + log.Debug("stream body - getReader") + bodyReader = external.NewStreamReader(jsBody.Call("getReader")) + } else { + log.Debug("unstremable body - fallback to ArrayBuffer") + // Fall back to using ArrayBuffer + // https://developer.mozilla.org/en-US/docs/Web/API/Body/arrayBuffer + bodyReader = external.NewArrayReader(request.Call("arrayBuffer")) + } + + bodyBytes, err := io.ReadAll(bodyReader) + if err != nil { + return nil, err + } + // TODO: that seems super awkward. we're constructing a reader only to fully consume it + // and create it all over again so that we the recipient wouldn't complain about content-length + // surely there must be a better way? + return bytes.NewReader(bodyBytes), nil +} + +func parseRedirect(request *js.Value) (string, error) { + redirect := request.Get(fieldRequestRedirect) + if redirect.IsUndefined() || redirect.IsNull() { + // "A Request has an associated Redirect Mode, which is "follow", "error", or "manual". Unless stated otherwise, it is "follow"." + // Reference: https://fetch.spec.whatwg.org/#concept-request + return jstypes.RequestRedirectFollow, nil + } + + if redirect.Type() != js.TypeString { + return "", errors.New("the redirect field is not a string") + } + + redirectString := redirect.String() + switch redirect.String() { + case jstypes.RequestRedirectManual: + return jstypes.RequestRedirectManual, nil + case jstypes.RequestRedirectError: + return jstypes.RequestRedirectError, nil + case jstypes.RequestRedirectFollow: + return jstypes.RequestRedirectFollow, nil + } + + return "", errors.New(fmt.Sprintf("%s is not a valid Redirect", redirectString)) +} + +func parseMode(request *js.Value, unsafeCors bool) (jstypes.Mode, error) { + if unsafeCors { + return jstypes.ModeUnsafeIgnoreCors, nil + } + + mode := request.Get(fieldRequestMode) + if mode.IsUndefined() || mode.IsNull() { + // "Even though the default Request Mode is "no-cors", standards are highly discouraged from using it for new features. It is rather unsafe." + // Reference: https://fetch.spec.whatwg.org/#concept-request-mode + return jstypes.ModeNoCors, nil + } + + if mode.Type() != js.TypeString { + return "", errors.New("the mode field is not a string") + } + + modeString := mode.String() + switch modeString { + case jstypes.ModeCors: + return jstypes.ModeCors, nil + case jstypes.ModeSameOrigin: + return jstypes.ModeSameOrigin, nil + case jstypes.ModeNoCors: + return jstypes.ModeNoCors, nil + case jstypes.ModeUnsafeIgnoreCors: + return jstypes.ModeUnsafeIgnoreCors, nil + case jstypes.ModeNavigate: + return "", errors.New(fmt.Sprintf("%s Mode is not supported", jstypes.ModeNavigate)) + case jstypes.ModeWebsocket: + return "", errors.New(fmt.Sprintf("%s Mode is not supported", jstypes.ModeWebsocket)) + } + + return "", errors.New(fmt.Sprintf("%s is not a valid Mode", modeString)) +} + +func parseCredentialsMode(request *js.Value) (jstypes.CredentialsMode, error) { + credentialsMode := request.Get(fieldRequestCredentials) + if credentialsMode.IsUndefined() || credentialsMode.IsNull() { + // A Request has an associated credentials Mode, which is "omit", "same-origin", or "include". Unless stated otherwise, it is "same-origin". + // Reference: https://fetch.spec.whatwg.org/#concept-request-mode + return jstypes.CredentialsModeSameOrigin, nil + } + + if credentialsMode.Type() != js.TypeString { + return "", errors.New("the credentials field is not a string") + } + + credentialsModeString := credentialsMode.String() + switch credentialsModeString { + case jstypes.CredentialsModeOmit: + return jstypes.CredentialsModeOmit, nil + case jstypes.CredentialsModeInclude: + return jstypes.CredentialsModeInclude, nil + case jstypes.CredentialsModeSameOrigin: + return jstypes.CredentialsModeSameOrigin, nil + } + + return "", errors.New(fmt.Sprintf("%s is not a valid credentials Mode", credentialsModeString)) +} + +func parseReferrer(request *js.Value) (jstypes.Referrer, error) { + referrer := request.Get(fieldRequestReferrer) + if referrer.IsUndefined() || referrer.IsNull() { + // A Request has an associated Referrer, which is "no-Referrer", "client", or a URL. Unless stated otherwise it is "client". + // Reference: https://fetch.spec.whatwg.org/#concept-request-referrer + return jstypes.ReferrerClient, nil + } + + if referrer.Type() != js.TypeString { + return "", errors.New("the referrer field is not a string") + } + + referrerString := referrer.String() + if referrerString == jstypes.ReferrerNoReferrer { + return jstypes.ReferrerNoReferrer, nil + } + + if referrerString == jstypes.ReferrerClient { + return jstypes.ReferrerClient, nil + } + + _, err := url.Parse(referrerString) + if err != nil { + return "", errors.New(fmt.Sprintf("\"%s\" is not a valid URL Referrer: \"%s\"", referrerString, err)) + } + return referrerString, nil +} + +func parseRefererPolicy(request *js.Value) (jstypes.ReferrerPolicy, error) { + referrerPolicy := request.Get(fieldRequestReferrerPolicy) + if referrerPolicy.IsUndefined() || referrerPolicy.IsNull() { + // A Request has an associated Referrer policy, which is a Referrer policy. Unless stated otherwise it is the empty string + // Reference: https://fetch.spec.whatwg.org/#concept-request-referrer-policy + return "", nil + } + + if referrerPolicy.Type() != js.TypeString { + return "", errors.New("the referrerPolicy field is not a string") + } + + referrerPolicyString := referrerPolicy.String() + switch referrerPolicyString { + case "": + return "", nil + case jstypes.ReferrerPolicyNoReferrer: + return jstypes.ReferrerPolicyNoReferrer, nil + case jstypes.ReferrerPolicyNoReferrerWhenDowngrade: + return jstypes.ReferrerPolicyNoReferrerWhenDowngrade, nil + case jstypes.ReferrerPolicyOrigin: + return jstypes.ReferrerPolicyOrigin, nil + case jstypes.ReferrerPolicyOriginWhenCrossOrigin: + return jstypes.ReferrerPolicyOriginWhenCrossOrigin, nil + case jstypes.ReferrerPolicySameOrigin: + return jstypes.ReferrerPolicySameOrigin, nil + case jstypes.ReferrerPolicyStrictOrigin: + return jstypes.ReferrerPolicyStrictOrigin, nil + case jstypes.ReferrerPolicyStrictOriginWhenCrossOrigin: + return jstypes.ReferrerPolicyStrictOriginWhenCrossOrigin, nil + case jstypes.ReferrerPolicyUnsafeUrl: + return jstypes.ReferrerPolicyUnsafeUrl, nil + } + + return "", errors.New(fmt.Sprintf("%s is not a valid Referrer policy", referrerPolicyString)) + +} + +func dealWithSignal(request *js.Value, cancel context.CancelFunc) error { + abortSignal := request.Get(fieldRequestSignal) + if abortSignal.IsUndefined() || abortSignal.IsNull() { + log.Debug("no abort signal passed") + return nil + } + if abortSignal.Type() != js.TypeObject { + return errors.New("passed abort signal is not a valid object") + } + + abortSignal.Call("addEventListener", "abort", js.FuncOf(func(this js.Value, args []js.Value) any { + log.Debug("abort signal called") + cancel() + return nil + })) + + return nil +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/jstypes/conv/response.go b/wasm/mix-fetch/go-mix-conn/internal/jstypes/conv/response.go new file mode 100644 index 0000000000..b1925a9582 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/jstypes/conv/response.go @@ -0,0 +1,350 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package conv + +import ( + "fmt" + "go-mix-conn/internal/external" + "go-mix-conn/internal/helpers" + "go-mix-conn/internal/jstypes" + "go-mix-conn/internal/log" + "go-mix-conn/internal/types" + "io" + "net/http" + "net/url" + "syscall/js" +) + +const ( + fieldResponseStatus = "status" + fieldResponseStatusText = "statusText" + fieldResponseRedirected = "redirected" + fieldResponseType = "type" + fieldResponseHeaders = "headers" + fieldResponseUrl = "url" +) + +type ResponseWrapper struct { + inner *http.Response + ctx *types.RequestContext +} + +func NewResponseWrapper(inner *http.Response, ctx *types.RequestContext) ResponseWrapper { + return ResponseWrapper{ + inner: inner, + ctx: ctx, + } +} + +type InternalResponse struct { + inner *http.Response + responseTainting jstypes.ResponseTainting + responseType jstypes.ResponseType + corsExposedHeaderName []string + urlList []*url.URL + wasRedirected bool +} + +func NewInternalResponse(inner *http.Response, reqOpts *types.RequestOptions, reqCtx *types.RequestContext) InternalResponse { + return InternalResponse{ + inner: inner, + responseTainting: reqOpts.ResponseTainting, + wasRedirected: reqCtx.WasRedirected, + } +} + +// Reference: https://fetch.spec.whatwg.org/#null-body-status +func (IR *InternalResponse) isNullBodyStatus() bool { + return IR.inner.StatusCode == 101 || IR.inner.StatusCode == 103 || IR.inner.StatusCode == 204 || IR.inner.StatusCode == 205 || IR.inner.StatusCode == 304 +} + +func (IR *InternalResponse) allHeaderNames() []string { + keys := make([]string, 0, len(IR.inner.Header)) + + for k, _ := range IR.inner.Header { + keys = append(keys, k) + } + return keys +} + +func (IR *InternalResponse) JSBody() (js.Value, error) { + if IR.inner.Body == nil { + return js.Undefined(), nil + } + + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + log.Error("failed to close the response body: %s", err) + } + }(IR.inner.Body) + + // Read the response body + // TODO: construct streamReader / arrayReader for better compat + data, err := io.ReadAll(IR.inner.Body) + if err != nil { + return js.Undefined(), err + } + + return helpers.IntoJsBytes(data), nil +} + +func (IR *InternalResponse) exposeHeadersNames() []string { + allowed := IR.inner.Header.Values(jstypes.HeaderExposeHeaders) + + allowedSet := external.NewSet(allowed...) + var filtered []string + for key, _ := range IR.inner.Header { + if allowedSet.Contains(key) { + filtered = append(filtered, key) + } + } + + return filtered +} + +// Reference: https://fetch.spec.whatwg.org/#concept-filtered-response-cors +func (IR *InternalResponse) mutIntoBasicResponse() { + IR.responseType = jstypes.ResponseTypeBasic + + newHeaders := http.Header{} + for key, values := range IR.inner.Header { + for _, value := range values { + if !jstypes.ForbiddenResponseHeaderNames.Contains(helpers.ByteLowercase(key)) { + ck := http.CanonicalHeaderKey(key) + newHeaders[ck] = append(newHeaders[ck], value) + } + } + } + IR.inner.Header = newHeaders +} + +// Reference: https://fetch.spec.whatwg.org/#concept-filtered-response-cors +func (IR *InternalResponse) mutIntoCORSResponse() { + IR.responseType = jstypes.ResponseTypeCors + + // TODO: figure out the proper usage of corsExposedHeaderName + + // https://github.com/mozilla/gecko-dev/blob/fabab5d10815c9d7210933379f0357b1cbc9aaaf/dom/fetch/InternalHeaders.cpp#L564 + newHeaders := http.Header{} + //for _, name := range IR.corsExposedHeaderName { + // if safelistedResponseHeaderNames.Contains(byteLowercase(name)) { + // ck := http.CanonicalHeaderKey(name) + // newHeaders[ck] = IR.inner.Header.Values(ck) + // } + //} + + for key, values := range IR.inner.Header { + for _, value := range values { + if jstypes.SafelistedResponseHeaderNames.Contains(helpers.ByteLowercase(key)) { + ck := http.CanonicalHeaderKey(key) + newHeaders[ck] = append(newHeaders[ck], value) + } + } + } + + IR.inner.Header = newHeaders +} + +// Reference: https://fetch.spec.whatwg.org/#concept-filtered-response-opaque +func (IR *InternalResponse) mutIntoOpaqueResponse() { + IR.responseType = jstypes.ResponseTypeOpaque + + // TODO: set URL list to « » + IR.inner.StatusCode = 0 + IR.inner.Status = "" + IR.inner.Header = http.Header{} + IR.inner.Body = nil +} + +// Reference: https://fetch.spec.whatwg.org/#concept-filtered-response-cors +func (IR *InternalResponse) mutIntoOpaqueRedirectResponse() { + IR.responseType = jstypes.ResponseTypeOpaqueRedirect + + IR.inner.StatusCode = 0 + IR.inner.Status = "" + IR.inner.Header = http.Header{} + IR.inner.Body = nil +} + +// OUTSIDE FETCH SPEC +func (IR *InternalResponse) mutIntoUnsafeIgnoreCorsResponse() { + IR.responseType = jstypes.ResponseTypeUnsafeIgnoreCors +} + +func proxyHandlerGet(proxied map[string]any) js.Func { + return js.FuncOf(func(_ js.Value, args []js.Value) any { + // Look at redirecting Method's this: + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy#no_private_property_forwarding + target := args[0] + prop := args[1].String() + receiver := args[2] + + value := target.Get(prop) + if value.Type() == js.TypeFunction { + log.Debug("%s is a function", prop) + return js.FuncOf(func(this js.Value, args []js.Value) any { + if this.Equal(receiver) { + return jstypes.Reflect.Call("apply", value, target, helpers.IntoAnySlice(args)) + } else { + return jstypes.Reflect.Call("apply", value, this, helpers.IntoAnySlice(args)) + } + }) + } + + // we're only proxing "normal" props, not function calls + proxy, ok := proxied[prop] + if ok { + log.Debug("using proxy value for field \"%s\" (changing \"%v\" -> \"%v\")", prop, value, proxy) + + return proxy + } + + return value + }) +} + +func responseProxyHandler(proxied map[string]any) js.Value { + handler := jstypes.Object.New() + handler.Set("get", proxyHandlerGet(proxied)) + return handler +} + +func (IR *InternalResponse) intoJsResponse() (js.Value, error) { + jsBody, err := IR.JSBody() + if err != nil { + return js.Undefined(), err + } + + // Create a Response object and pass the data + // inspired by https://github.com/golang/go/blob/release-branch.go1.21/src/net/http/roundtrip_js.go#L91 + headers := jstypes.Headers.New() + for key, values := range IR.inner.Header { + for _, value := range values { + headers.Call("append", key, value) + } + } + + responseOptions := jstypes.Object.New() + responseOptions.Set(fieldResponseStatus, IR.inner.StatusCode) + responseOptions.Set(fieldResponseStatusText, http.StatusText(IR.inner.StatusCode)) + responseOptions.Set(fieldResponseHeaders, headers) + + proxied := make(map[string]any) + + if IR.responseType != "" { + proxied[fieldResponseType] = IR.responseType + } + + // can't call the constructor properly if the value is outside the "legal" range (i.e. [200, 599]) + // (even though the fetch spec requires something different...) + if IR.inner.StatusCode == 0 { + responseOptions.Set(fieldResponseStatus, 418) + proxied[fieldResponseStatus] = IR.inner.StatusCode + } + + if len(IR.urlList) > 0 { + // "The value of the url property will be the final URL obtained after any redirects." + // source: https://developer.mozilla.org/en-US/docs/Web/API/Response/url + last := IR.urlList[len(IR.urlList)-1] + proxied[fieldResponseUrl] = last.String() + } + + if IR.wasRedirected { + proxied[fieldResponseRedirected] = IR.wasRedirected + } + + responseConstructor := jstypes.Response + response := responseConstructor.New(jsBody, responseOptions) + + for k, v := range proxied { + response.Set(fmt.Sprintf("_%s", k), v) + } + + proxyConstructor := jstypes.Proxy + proxy := proxyConstructor.New(response, responseProxyHandler(proxied)) + + return proxy, nil +} + +// IntoJSResponse is a reverse of https://github.com/golang/go/blob/release-branch.go1.21/src/net/http/roundtrip_js.go#L91 +// https://developer.mozilla.org/en-US/docs/Web/API/response +/* + Response attributes and their implementation status: + [✅] - supported + [⚠️] - partially supported (some features might be missing) + [❌] - unsupported + [❗] - not applicable / will not support + + [⚠️] body - response streaming via ReadableStream is unsupported (TODO: look into https://github.com/golang/go/blob/release-branch.go1.21/src/net/http/roundtrip_js.go#L152-L195 to implement it) + [✅] bodyUsed + [✅] headers + [✅] ok - seems to be handled automagically (presumably via `status`) + [✅] redirected - has to be proxied + [✅] status - has to be proxied when status == 0 + [✅] statusText + [✅] type - has to be proxied + [⚠️] url - not sure if every case is covered +*/ +func IntoJSResponse(resp *ResponseWrapper, opts *types.RequestOptions) (js.Value, error) { + // TODO: check if response is a filtered response + isFilteredResponse := false + + // result of 4.3.6.2.2 + internalResponse := NewInternalResponse(resp.inner, opts, resp.ctx) + if resp.ctx.OverwrittenResponseType == jstypes.ResponseTypeOpaqueRedirect { + isFilteredResponse = true + internalResponse.mutIntoOpaqueRedirectResponse() + } + + // 4.1.14 + if !isFilteredResponse { + // 4.1.14.1 + if opts.ResponseTainting == jstypes.ResponseTaintingCors { + // 4.1.14.1.1 + headerNames := internalResponse.exposeHeadersNames() + if opts.CredentialsMode != jstypes.CredentialsModeInclude && helpers.Contains(headerNames, jstypes.Wildcard) { + // 4.1.14.1.2 + internalResponse.corsExposedHeaderName = helpers.Unique(internalResponse.allHeaderNames()) + } else if len(headerNames) > 0 { + // 4.1.14.1.3 + internalResponse.corsExposedHeaderName = headerNames + } + } + switch opts.ResponseTainting { + case jstypes.ResponseTaintingBasic: + internalResponse.mutIntoBasicResponse() + case jstypes.ResponseTaintingCors: + internalResponse.mutIntoCORSResponse() + case jstypes.ResponseTaintingOpaque: + internalResponse.mutIntoOpaqueResponse() + case jstypes.ResponseTaintingUnsafeIgnoreCors: + internalResponse.mutIntoUnsafeIgnoreCorsResponse() + default: + panic("unreachable") + } + } + + if len(internalResponse.urlList) == 0 { + internalResponse.urlList = []*url.URL{internalResponse.inner.Request.URL} + } + // TODO: 4.1.17 - Redirect-tainted origin + // TODO: 4.1.18 - timing allow flag + + // TODO: 4.1.19 - mixed content check + // TODO: 4.1.19 - Content Security Policy check + // TODO: 4.1.19 - MIME type check + // TODO: 4.1.19 - nosniff check + + // TODO: 4.1.20 + //rangeRequestedFlag := false + //if internalResponse.responseType == types.RESPONSE_TYPE_OPAQUE && internalResponse.inner.Status == 206 + + // 4.1.21 + if (opts.Method == "HEAD" || opts.Method == "CONNECT") || internalResponse.isNullBodyStatus() { + internalResponse.inner.Body = nil + } + + return internalResponse.intoJsResponse() +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/jstypes/globals.go b/wasm/mix-fetch/go-mix-conn/internal/jstypes/globals.go new file mode 100644 index 0000000000..51dda48c8e --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/jstypes/globals.go @@ -0,0 +1,39 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package jstypes + +import ( + "fmt" + "net/url" + "syscall/js" +) + +var ( + Error = js.Global().Get("Error") + Promise = js.Global().Get("Promise") + Reflect = js.Global().Get("Reflect") + Object = js.Global().Get("Object") + Response = js.Global().Get("Response") + Request = js.Global().Get("Request") + Proxy = js.Global().Get("Proxy") + Headers = js.Global().Get("Headers") +) + +func Origin() string { + // nodejs doesn't have origin + location := js.Global().Get("location") + if !location.IsUndefined() && !location.IsNull() { + return location.Get("origin").String() + } else { + return "" + } +} + +func OriginUrl() *url.URL { + originUrl, originErr := url.Parse(Origin()) + if originErr != nil { + panic(fmt.Sprintf("could not obtain origin: %s", originErr)) + } + return originUrl +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/jstypes/headers.go b/wasm/mix-fetch/go-mix-conn/internal/jstypes/headers.go new file mode 100644 index 0000000000..d32ac89bd2 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/jstypes/headers.go @@ -0,0 +1,102 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package jstypes + +import ( + "go-mix-conn/internal/external" + "go-mix-conn/internal/helpers" +) + +const ( + HeaderOrigin = "Origin" + + HeaderRequestMethod = "Access-Control-Request-Method" + HeaderRequestHeaders = "Access-Control-Request-Headers" + HeaderRequestLocalNetwork = "Access-Control-Request-Local-Network" + HeaderRequestPrivateNetwork = "Access-Control-Request-Private-Network" + + HeaderAllowMethods = "Access-Control-Allow-Methods" + HeaderAllowHeaders = "Access-Control-Allow-Headers" + HeaderMageAge = "Access-Control-Max-Age" + HeaderAllowLocalNetwork = "Access-Control-Allow-Local-Network" + HeaderAllowPrivateNetwork = "Access-Control-Allow-Private-Network" + + // Indicates whether the response can be shared, via returning the literal value of the `Origin` request header (which can be `null`) or `*` in a response. + HeaderAllowOrigin = "Access-Control-Allow-Origin" + // Indicates whether the response can be shared when request’s credentials mode is "include". + HeaderAllowCredentials = "Access-Control-Allow-Credentials" + + HeaderExposeHeaders = "Access-Control-Expose-Headers" + + Wildcard = "*" +) + +// see https://fetch.spec.whatwg.org/#forbidden-header-name +var DiscreteForbiddenHeaderNames = external.NewSet( + "accept-charset", + "accept-encoding", + helpers.ByteLowercase(HeaderRequestHeaders), + helpers.ByteLowercase(HeaderRequestMethod), + // see https://wicg.github.io/local-network-access/#forbidden-header-names + helpers.ByteLowercase(HeaderRequestLocalNetwork), + helpers.ByteLowercase(HeaderRequestPrivateNetwork), + "connection", + "content-length", + "cookie", + "cookie2", + "date", + "dnt", + "expect", + "host", + "keep-alive", + helpers.ByteLowercase(HeaderOrigin), + "referer", + "set-cookie", + "te", + "trailer", + "transfer-encoding", + "upgrade", + "via", +) + +// almost always a mistake to allow the following as request headers +// as a result of misunderstanding of the CORS protocol. +var DisallowedRequestHeaderNames = external.NewSet( + helpers.ByteLowercase(Wildcard), + helpers.ByteLowercase(HeaderAllowOrigin), + helpers.ByteLowercase(HeaderAllowCredentials), + helpers.ByteLowercase(HeaderAllowMethods), + helpers.ByteLowercase(HeaderAllowHeaders), + helpers.ByteLowercase(HeaderAllowLocalNetwork), + helpers.ByteLowercase(HeaderAllowPrivateNetwork), + helpers.ByteLowercase(HeaderMageAge), + helpers.ByteLowercase(HeaderExposeHeaders), +) + +// almost always a mistake to expose the following as response headers +var DisallowedResponseHeaderNames = external.NewSet( + helpers.ByteLowercase(Wildcard), + helpers.ByteLowercase(HeaderOrigin), + helpers.ByteLowercase(HeaderRequestMethod), + helpers.ByteLowercase(HeaderRequestHeaders), + helpers.ByteLowercase(HeaderRequestLocalNetwork), + helpers.ByteLowercase(HeaderRequestPrivateNetwork), +) + +// see https://fetch.spec.whatwg.org/#forbidden-response-header-name +var ForbiddenResponseHeaderNames = external.NewSet( + "set-cookie", + "set-cookie2", +) + +// see https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name +var SafelistedResponseHeaderNames = external.NewSet( + "cache-control", + "content-language", + "content-length", + "content-type", + "expires", + "last-modified", + "pragma", +) diff --git a/wasm/mix-fetch/go-mix-conn/internal/jstypes/helpers.go b/wasm/mix-fetch/go-mix-conn/internal/jstypes/helpers.go new file mode 100644 index 0000000000..ba10a05196 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/jstypes/helpers.go @@ -0,0 +1,140 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package jstypes + +import ( + "go-mix-conn/internal/helpers" + "go-mix-conn/internal/log" + "net/http" + "net/url" + "strings" +) + +// see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2 +func IsValidHeaderName(raw string) bool { + return helpers.IsToken(raw) +} + +// see https://fetch.spec.whatwg.org/#forbidden-header-name +func IsForbiddenRequestHeaderName(name string) bool { + if DiscreteForbiddenHeaderNames.Contains(name) { + return true + } + return strings.HasPrefix(name, "proxy-") || + strings.HasPrefix(name, "sec-") +} + +// A CORS-unsafe request-header byte is a byte *byte* for which one of the following is true: +// - byte is less than 0x20 and is not 0x09 HT +// - byte is 0x22 ("), 0x28 (left parenthesis), 0x29 (right parenthesis), 0x3A (:), 0x3C (<), 0x3E (>), 0x3F (?), 0x40 (@), 0x5B ([), 0x5C (\), 0x5D (]), 0x7B ({), 0x7D (}), or 0x7F DEL. +// Reference: https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte +func containsCORSUnsafeRequestHeaderByte(b []byte) bool { + for i := 0; i < len(b); i++ { + v := b[i] + if v < 0x20 && v != 0x09 { + return true + } + if v == 0x22 || v == 0x28 || v == 0x29 || v == 0x3A || v == 0x3C || v == 0x3E || v == 0x3F || v == 0x40 || v == 0x5B || v == 0x5C || v == 0x5D || v == 0x7B || v == 0x7D || v == 0x7F { + return true + } + } + + return false +} + +// Reference: https://fetch.spec.whatwg.org/#cors-safelisted-request-header +func isCorsSafelistedRequestHeader(name string, value string) bool { + // 1 + if len(value) > 128 { + return false + } + + // 2 + switch helpers.ByteLowercase(name) { + case "accept": + if containsCORSUnsafeRequestHeaderByte([]byte(value)) { + return false + } + case "accept-language", "content-language": + valueBytes := []byte(value) + for i := 0; i < len(valueBytes); i++ { + v := valueBytes[i] + if !(0x30 <= v && v <= 0x39) && !(0x41 <= v && v <= 0x5A) && !(0x61 <= v && v <= 0x7A) && v != 0x20 && v != 0x2A && v != 0x2C && v != 0x2D && v != 0x2E && v != 0x3B && v != 0x3D { + return false + } + } + case "content-type": + // 2.1 + if containsCORSUnsafeRequestHeaderByte([]byte(value)) { + return false + } + // 2.4 + if value != "application/x-www-form-urlencoded" && value != "multipart/form-data" && value != "text/plain" { + return false + } + case "range": + log.Error("unimplemented 'range' header") + return false + default: + return false + } + + // 3 + return true +} + +// Reference: https://fetch.spec.whatwg.org/#cors-unsafe-request-header-names +func CorsUnsafeRequestHeaderNames(headers http.Header) []string { + var unsafeNames []string + var potentiallyUnsafeNames []string + safelistValueSize := 0 + + // 4 + for name, value := range headers { + // TODO: is that actually correct? + wasUnsafe := false + for _, v := range value { + // 4.1 + if !isCorsSafelistedRequestHeader(name, v) { + unsafeNames = append(unsafeNames, name) + wasUnsafe = true + break + } + } + if !wasUnsafe { + potentiallyUnsafeNames = append(potentiallyUnsafeNames, name) + safelistValueSize += len(value) + } + } + + // 5 + if safelistValueSize > 1024 { + for _, name := range potentiallyUnsafeNames { + unsafeNames = append(unsafeNames, name) + } + } + + return helpers.SortedByteLowercase(unsafeNames) +} + +// Reference: https://fetch.spec.whatwg.org/#cors-safelisted-method +func IsCorsSafelistedMethod(method string) bool { + if method == "GET" || method == "HEAD" || method == "POST" { + return true + } else { + return false + } +} + +func IsSameOrigin(remoteUrl *url.URL) bool { + originUrl := OriginUrl() + + // Roughly speaking, two URIs are part of the same JsOrigin (i.e., represent the same principal) + // if they have the same scheme, host, and port. + // Reference: https://www.rfc-editor.org/rfc/rfc6454.html#section-3.2 + if originUrl.Scheme != remoteUrl.Scheme || originUrl.Host != remoteUrl.Host || originUrl.Port() != remoteUrl.Port() { + return false + } + return true +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/jstypes/request.go b/wasm/mix-fetch/go-mix-conn/internal/jstypes/request.go new file mode 100644 index 0000000000..79ec5a1e62 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/jstypes/request.go @@ -0,0 +1,45 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package jstypes + +type Redirect = string +type Mode = string +type CredentialsMode = string +type ResponseTainting = string +type ReferrerPolicy = string +type Referrer = string + +const ( + RequestRedirectError = "error" + RequestRedirectManual = "manual" + RequestRedirectFollow = "follow" + + ResponseTaintingBasic = "basic" + ResponseTaintingCors = "cors" + ResponseTaintingOpaque = "opaque" + ResponseTaintingUnsafeIgnoreCors = "ignore-cors" + + ModeCors = "cors" + ModeSameOrigin = "same-origin" + ModeNoCors = "no-cors" + ModeNavigate = "navigate" + ModeWebsocket = "websocket" + ModeUnsafeIgnoreCors = "unsafe-ignore-cors" + + CredentialsModeOmit = "omit" + CredentialsModeSameOrigin = "same-origin" + CredentialsModeInclude = "include" + + ReferrerPolicyNoReferrer = "no-referrer" + ReferrerPolicyNoReferrerWhenDowngrade = "no-referrer-when-downgrade" + ReferrerPolicyOrigin = "origin" + ReferrerPolicyOriginWhenCrossOrigin = "origin-when-cross-origin" + ReferrerPolicySameOrigin = "same-origin" + ReferrerPolicyStrictOrigin = "strict-origin" + ReferrerPolicyStrictOriginWhenCrossOrigin = "strict-origin-when-cross-origin" + ReferrerPolicyUnsafeUrl = "unsafe-url" + + ReferrerNoReferrer = "no-referrer" + ReferrerClient = "client" +) diff --git a/wasm/mix-fetch/go-mix-conn/internal/jstypes/response.go b/wasm/mix-fetch/go-mix-conn/internal/jstypes/response.go new file mode 100644 index 0000000000..e0f2644347 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/jstypes/response.go @@ -0,0 +1,16 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package jstypes + +type ResponseType = string + +const ( + ResponseTypeBasic = "basic" + ResponseTypeCors = "cors" + ResponseTypeDefault = "default" + ResponseTypeError = "error" + ResponseTypeOpaque = "opaque" + ResponseTypeOpaqueRedirect = "opaqueredirect" + ResponseTypeUnsafeIgnoreCors = "unsafe-ignore-cors" +) diff --git a/wasm/mix-fetch/go-mix-conn/internal/log/logger.go b/wasm/mix-fetch/go-mix-conn/internal/log/logger.go new file mode 100644 index 0000000000..78aafd0107 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/log/logger.go @@ -0,0 +1,100 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package log + +import ( + "fmt" + "runtime" + "strings" + "syscall/js" +) + +type LogLevel = int + +const ( + DISABLED LogLevel = iota + ERROR + WARN + INFO + DEBUG + TRACE +) + +var ( + // thanks to the amazing capabilities of this awesome language, + // we couldn't put it in the `jstypes` alongside other globals + // as it created an unresolvable cyclic import + console = js.Global().Get("console") + + GlobalLogLevel = INFO +) + +func SetLoggingLevel(raw string) { + switch strings.ToLower(raw) { + case "disabled": + GlobalLogLevel = DISABLED + case "error": + GlobalLogLevel = ERROR + case "warn", "warning": + GlobalLogLevel = WARN + case "info": + GlobalLogLevel = INFO + case "debug": + GlobalLogLevel = DEBUG + case "trace": + GlobalLogLevel = TRACE + default: + Warn("\"%s\" is not a valid logging level", raw) + } +} + +func makeLogMessage(severity string, format string, a ...any) string { + _, file, line, ok := runtime.Caller(2) + // we should really be using a mutex here... + if !ok { + file = "???" + line = 0 + } + + prefix := fmt.Sprintf("[go] %s: %s:%d: ", severity, file, line) + suffix := fmt.Sprintf(format, a...) + return prefix + suffix +} + +func Error(format string, a ...any) { + if GlobalLogLevel >= ERROR { + msg := makeLogMessage("ERROR", format, a...) + console.Call("error", msg) + } +} + +func Warn(format string, a ...any) { + if GlobalLogLevel >= WARN { + msg := makeLogMessage("WARN", format, a...) + console.Call("warn", msg) + } +} + +func Info(format string, a ...any) { + if GlobalLogLevel >= INFO { + msg := makeLogMessage("INFO", format, a...) + console.Call("info", msg) + } +} + +func Debug(format string, a ...any) { + if GlobalLogLevel >= DEBUG { + msg := makeLogMessage("DEBUG", format, a...) + // too lazy to configure my console : ) + // console.Call("debug", msg) + console.Call("log", msg) + } +} + +func Trace(format string, a ...any) { + if GlobalLogLevel >= TRACE { + msg := makeLogMessage("TRACE", format, a...) + console.Call("log", msg) + } +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/mixfetch/helpers.go b/wasm/mix-fetch/go-mix-conn/internal/mixfetch/helpers.go new file mode 100644 index 0000000000..23a91b725b --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/mixfetch/helpers.go @@ -0,0 +1,59 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package mixfetch + +import ( + "golang.org/x/net/idna" + "net" + "net/url" + "unicode" +) + +var portMap = map[string]string{ + "http": "80", + "https": "443", + "socks5": "1080", +} + +// canonicalAddr returns url.Host but always with a ":port" suffix. +// source: https://github.com/golang/go/blob/release-branch.go1.20/src/net/http/transport.go#L2747 +func canonicalAddr(url *url.URL) string { + addr := url.Hostname() + if v, err := idnaASCII(addr); err == nil { + addr = v + } + port := url.Port() + if port == "" { + port = portMap[url.Scheme] + } + return net.JoinHostPort(addr, port) +} + +// source: https://github.com/golang/go/blob/release-branch.go1.20/src/net/http/request.go#L724 +func idnaASCII(v string) (string, error) { + // TODO: Consider removing this check after verifying performance is okay. + // Right now punycode verification, length checks, context checks, and the + // permissible character tests are all omitted. It also prevents the ToASCII + // call from salvaging an invalid IDN, when possible. As a result it may be + // possible to have two IDNs that appear identical to the user where the + // ASCII-only version causes an error downstream whereas the non-ASCII + // version does not. + // Note that for correct ASCII IDNs ToASCII will only do considerably more + // work, but it will not cause an allocation. + if isAscii(v) { + return v, nil + } + return idna.Lookup.ToASCII(v) +} + +// isAscii returns whether s is ASCII. +// source: https://github.com/golang/go/blob/release-branch.go1.20/src/net/http/internal/ascii/print.go#L46 +func isAscii(s string) bool { + for i := 0; i < len(s); i++ { + if s[i] > unicode.MaxASCII { + return false + } + } + return true +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/mixfetch/mixfetch.go b/wasm/mix-fetch/go-mix-conn/internal/mixfetch/mixfetch.go new file mode 100644 index 0000000000..3dbc4c077f --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/mixfetch/mixfetch.go @@ -0,0 +1,362 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package mixfetch + +import ( + "context" + "errors" + "fmt" + "go-mix-conn/internal/bridge/rust_bridge" + "go-mix-conn/internal/jstypes" + "go-mix-conn/internal/jstypes/conv" + "go-mix-conn/internal/log" + "go-mix-conn/internal/state" + "go-mix-conn/internal/types" + "net" + "net/http" + "net/url" + "time" +) + +func inRedirectionLoop(req *http.Request, via []*http.Request) bool { + target := req.URL.String() + + for i := 0; i < len(via); i++ { + if target == via[i].URL.String() { + return true + } + } + return false +} + +func checkRedirect(ctx *types.RequestContext, opts *types.RequestOptions, req *http.Request, via []*http.Request) error { + log.Debug("attempting to perform redirection to %s with our policy set to '%s'", req.URL.String(), opts.Redirect) + + if len(via) > state.MaxRedirections { + return errors.New(fmt.Sprintf("Maximum (%d) redirects followed", state.MaxRedirections)) + } + + if inRedirectionLoop(req, via) { + return errors.New("stuck in redirection loop") + } + + redirectionChain := "" + for i := 0; i < len(via); i++ { + redirectionChain += fmt.Sprintf("%s -> ", via[i].URL.String()) + } + redirectionChain += fmt.Sprintf("[%s]", req.URL.String()) + log.Debug("redirection chain: %s", redirectionChain) + + // Reference: https://fetch.spec.whatwg.org/#http-fetch + // 4.3.6.2 + switch opts.Redirect { + case jstypes.RequestRedirectError: + return errors.New("encountered redirect") + case jstypes.RequestRedirectManual: + if opts.Mode == jstypes.ModeNavigate { + return errors.New("unimplemented 'navigate' + 'manual' redirection") + } + ctx.OverwrittenResponseType = jstypes.ResponseTypeOpaqueRedirect + return http.ErrUseLastResponse + case jstypes.RequestRedirectFollow: + log.Debug("will perform redirection") + // this feels so nasty... + ctx.WasRedirected = true + return nil + default: + // if this was rust that had proper enums and match statements, + // we could have guaranteed that at compile time... + panic("unreachable") + } +} + +// 4.1.12 +// Reference: https://fetch.spec.whatwg.org/#main-fetch +func mainFetchChecks(req *conv.ParsedRequest) error { + // >>> START: NOT INCLUDED IN FETCH SPEC + if req.Options.Mode == jstypes.ModeUnsafeIgnoreCors { + // ignore all checks - everything should be accepted + req.Options.ResponseTainting = jstypes.ResponseTaintingUnsafeIgnoreCors + return nil + } + // >>> END: NOT INCLUDED IN FETCH SPEC + + // no preloading + + if (jstypes.IsSameOrigin(req.Request.URL) && req.Options.ResponseTainting == jstypes.ResponseTaintingBasic) || + req.Request.URL.Scheme == "data" || (req.Options.Mode == jstypes.ModeNavigate || req.Options.Mode == jstypes.ModeWebsocket) { + log.Debug("setting response tainting to basic") + req.Options.ResponseTainting = jstypes.ResponseTaintingBasic + // TODO: scheme fetch here + return nil + } + if req.Options.Mode == jstypes.ModeSameOrigin { + return errors.New(fmt.Sprintf("MixFetch API cannot load %s. Request mode is \"%s\" but the URL's origin is not same as the request origin %s.", req.Request.URL.String(), jstypes.ModeSameOrigin, jstypes.Origin)) + } + if req.Options.Mode == jstypes.ModeNoCors { + if req.Options.Redirect != jstypes.RequestRedirectFollow { + return errors.New(fmt.Sprintf("MixFetch API cannot load %s. Request mode is \"%s\", but the redirect mode is not \"%s\".", req.Request.URL.String(), req.Options.Mode, jstypes.RequestRedirectFollow)) + } + log.Debug("setting response tainting to opaque") + req.Options.ResponseTainting = jstypes.ResponseTaintingOpaque + // TODO: scheme fetch here + return nil + } + if req.Request.URL.Scheme != "http" && req.Request.URL.Scheme != "https" { + return errors.New(fmt.Sprintf("The requested url scheme (\"%s\" is not http(s)", req.Request.URL.Scheme)) + } + + // TODO: CORS-preflight flag + // TODO: unsafe-request flag + // (by default they're unset) + corsPreflightFlag := false + unsafeRequestFlag := false + + if corsPreflightFlag || (unsafeRequestFlag && (jstypes.IsCorsSafelistedMethod(req.Request.Method) || len(jstypes.CorsUnsafeRequestHeaderNames(req.Request.Header)) > 0)) { + req.Options.ResponseTainting = jstypes.ResponseTaintingCors + panic("unimplemented \"corsWithPreflightResponse\"") + } + + req.Options.ResponseTainting = jstypes.ResponseTaintingCors + log.Debug("setting response tainting to cors") + // TODO: HTTP fetch here + return nil +} + +func schemeFetch(req *conv.ParsedRequest) error { + switch req.Request.URL.Scheme { + case "about": + return errors.New("unsupported 'about' scheme") + case "blob": + return errors.New("unsupported 'blob' scheme") + case "data": + return errors.New("unsupported 'data' scheme") + case "file": + return errors.New("unsupported 'file' scheme") + case "http", "https": + // TODO: HTTP fetch here + return nil + default: + return errors.New("unknown url scheme") + } +} + +func dialContext(_ctx context.Context, opts *types.RequestOptions, _network, addr string) (net.Conn, error) { + log.Debug("dialing plain connection to %s", addr) + + requestId, err := rust_bridge.RsStartNewMixnetRequest(addr) + if err != nil { + return nil, err + } + if state.ActiveRequests.Exists(requestId) { + return nil, errors.New(fmt.Sprintf("somehow opened duplicate connection with id %d", requestId)) + } + + conn, inj := state.NewFakeConnection(requestId, addr) + state.ActiveRequests.Insert(requestId, addr, inj) + + return conn, nil +} + +func dialTLSContext(_ctx context.Context, opts *types.RequestOptions, _network, addr string) (net.Conn, error) { + log.Debug("dialing TLS connection to %s", addr) + + requestId, err := rust_bridge.RsStartNewMixnetRequest(addr) + if err != nil { + return nil, err + } + if state.ActiveRequests.Exists(requestId) { + return nil, errors.New(fmt.Sprintf("somehow opened duplicate connection with id %d", requestId)) + } + + conn, inj := state.NewFakeTlsConn(requestId, addr) + state.ActiveRequests.Insert(requestId, addr, inj) + + if err := conn.Handshake(); err != nil { + return nil, err + } + + return conn, nil +} + +func buildHttpClient(reqCtx *types.RequestContext, opts *types.RequestOptions) *http.Client { + return &http.Client{ + CheckRedirect: func(req *http.Request, via []*http.Request) error { + return checkRedirect(reqCtx, opts, req, via) + }, + + Transport: &http.Transport{ + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + return dialContext(ctx, opts, network, addr) + }, + DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + return dialTLSContext(ctx, opts, network, addr) + }, + + //TLSClientConfig: &tlsConfig, + DisableKeepAlives: true, + MaxIdleConns: 1, + MaxIdleConnsPerHost: 1, + MaxConnsPerHost: 1, + }, + Timeout: state.RequestTimeout, + } +} + +func CloseRemoteSocket(requestId types.RequestId) any { + state.ActiveRequests.CloseRemoteSocket(requestId) + return nil +} + +func InjectServerData(requestId types.RequestId, data []byte) any { + state.ActiveRequests.InjectData(requestId, data) + return nil +} + +func InjectConnError(requestId types.RequestId, err error) any { + state.ActiveRequests.SendError(requestId, err) + return nil +} + +func ChangeRequestTimeout(timeout time.Duration) any { + log.Debug("changing request timeout to %v", timeout) + state.RequestTimeout = timeout + return nil +} + +// Reference: https://fetch.spec.whatwg.org/#cors-check +func doCorsCheck(reqOpts *types.RequestOptions, resp *http.Response) error { + // 4.9.1 + originHeader := resp.Header.Get(jstypes.HeaderAllowOrigin) + // 4.9.2 + if originHeader == "" { + return errors.New(fmt.Sprintf("\"%s\" header not present on remote", jstypes.HeaderAllowOrigin)) + } + + if reqOpts.CredentialsMode != jstypes.CredentialsModeInclude && originHeader == jstypes.Wildcard { + // 4.9.3 + return nil + } + + // 4.9.4 + // TODO: presumably this needs to better account for the wildcard? + if jstypes.Origin() != originHeader { + return errors.New(fmt.Sprintf("\"%s\" does not match the origin \"%s\" on \"%s\" remote header", jstypes.Origin, originHeader, jstypes.HeaderAllowOrigin)) + } + + // 4.9.5 + if reqOpts.CredentialsMode != jstypes.CredentialsModeInclude { + return nil + } + + // 4.9.6 + credentials := resp.Header.Get(jstypes.HeaderAllowCredentials) + // 4.9.7 + if credentials == "true" { + return nil + } + + // 4.9.8 + return errors.New("failed cors check") +} + +func performRequest(req *conv.ParsedRequest) (*conv.ResponseWrapper, error) { + err := mainFetchChecks(req) + if err != nil { + return nil, err + } + + reqCtx := &types.RequestContext{} + + reqClient := buildHttpClient(reqCtx, req.Options) + + if req.Options.ReferrerPolicy == "" { + // 4.1.8 + // Reference: https://fetch.spec.whatwg.org/#main-fetch + // TODO: implement + log.Warn("unimplemented: could not obtain referrer policy from the policy container") + } + + if req.Options.Referrer != jstypes.ReferrerNoReferrer { + // 4.1.9 + // Reference: https://fetch.spec.whatwg.org/#main-fetch + // TODO: implement + log.Warn("unimplemented: could not determine request's referrer") + } + + // TODO: this is such a nasty assumption, but assume we're doing a 4.3 HTTP fetch here + + log.Info("Starting the request...") + log.Debug("%v: %v", req.Options, *req.Request) + // TODO: CORS preflight... + + resp, err := reqClient.Do(req.Request) + if err != nil { + return nil, err + } + + // 4.3.4.4 + if req.Options.ResponseTainting == jstypes.ResponseTaintingCors { + err = doCorsCheck(req.Options, resp) + if err != nil { + return nil, err + } + } + // TODO: policy checks, etc... + + wrapper := conv.NewResponseWrapper(resp, reqCtx) + + return &wrapper, err +} + +func onErrCleanup(url *url.URL) { + // TODO: cancel stuff here.... somehow... + + canonicalAddr := canonicalAddr(url) + id := state.ActiveRequests.GetId(canonicalAddr) + // TODO: can we guarantee that rust is not holding any references to that id (that we don't know on this side)? + if id == 0 { + // if id doesn't exist it [probably] means the error was thrown before the request was properly created + log.Debug("there doesn't seem to exist a request associated with addr %s", canonicalAddr) + return + } + state.ActiveRequests.Remove(id) + err := rust_bridge.RsFinishMixnetConnection(id) + if err != nil { + // TODO: can we do anything else in here? + log.Error("failed to properly abort the request: %s", err) + } +} + +func MixFetch(request *conv.ParsedRequest) (any, error) { + log.Info("_mixFetch: start") + + canonical := canonicalAddr(request.Request.URL) + if state.ActiveRequests.ExistsCanonical(canonical) { + // TODO: how to deal with it to allow for concurrent requests to say `https://foo.com/index.html` and `https://foo.com/index.js`? + return nil, errors.New(fmt.Sprintf("there is already an active request for %s", canonical)) + } + + resCh := make(chan *conv.ResponseWrapper) + errCh := make(chan error) + go func(resCh chan *conv.ResponseWrapper, errCh chan error) { + resp, err := performRequest(request) + if err != nil { + errCh <- err + } else { + resCh <- resp + } + }(resCh, errCh) + + select { + case res := <-resCh: + log.Debug("finished performing the request") + log.Trace("response: %+v", *res) + return conv.IntoJSResponse(res, request.Options) + case err := <-errCh: + log.Warn("request failure: %s", err) + onErrCleanup(request.Request.URL) + return nil, err + } +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/sslhelpers/root_certs.go b/wasm/mix-fetch/go-mix-conn/internal/sslhelpers/root_certs.go new file mode 100644 index 0000000000..361fbc7b06 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/sslhelpers/root_certs.go @@ -0,0 +1,3235 @@ +package sslhelpers + +import ( + "crypto/x509" + "go-mix-conn/internal/log" +) + +// source: https://curl.se/ca/cacert-2023-05-30.pem +// sha256 when downloaded: 5fadcae90aa4ae041150f8e2d26c37d980522cdb49f923fc1e1b5eb8d74e71ad cacert.pem +func rawCerts() [][]byte { + var certs [][]byte + + //GlobalSign Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx +GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds +b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD +VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa +DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc +THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb +Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP +c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX +gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF +AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj +Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG +j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH +hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC +X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE-----`)) + + //Entrust.net Premium 2048 Secure Server CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u +ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp +bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx +NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 +d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u +ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL +Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr +hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW +nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi +VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ +KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy +T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT +J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e +nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= +-----END CERTIFICATE-----`)) + + //Baltimore CyberTrust Root + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE +ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li +ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC +SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs +dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME +uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB +UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C +G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 +XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr +l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI +VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB +BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh +cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 +hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa +Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H +RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE-----`)) + + //Entrust Root Certification Authority + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw +b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG +A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 +MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu +MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz +A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww +Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 +j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN +rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 +MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH +hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM +Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa +v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS +W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 +tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE-----`)) + + //Comodo AAA Services root + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw +MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl +c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV +BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG +C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs +i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW +Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH +Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK +Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f +BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl +cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz +LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm +7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z +8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C +12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE-----`)) + + //QuoVadis Root CA 2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx +ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6 +XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk +lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB +lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy +lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt +66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn +wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh +D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy +BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie +J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud +DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU +a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv +Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3 +UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm +VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK ++JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW +IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1 +WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X +f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II +4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8 +VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE-----`)) + + //QuoVadis Root CA 3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx +OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg +DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij +KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K +DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv +BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp +p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8 +nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX +MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM +Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz +uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT +BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj +YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB +BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD +VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4 +ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE +AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV +qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s +hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z +POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2 +Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp +8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC +bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu +g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p +vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr +qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE-----`)) + + //Security Communication Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw +8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM +DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX +5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd +DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 +JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g +0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a +mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ +s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ +6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi +FL39vmwLAw== +-----END CERTIFICATE-----`)) + + //XRamp Global CA Root + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE +BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj +dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx +HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg +U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu +IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx +foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE +zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs +AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry +xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap +oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC +AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc +/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n +nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz +8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE-----`)) + + //Go Daddy Class 2 CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY +VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG +A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g +RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD +ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv +2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 +qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j +YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY +vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O +BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o +atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu +MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim +PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt +I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI +Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b +vZ8= +-----END CERTIFICATE-----`)) + + //Starfield Class 2 CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc +U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo +MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG +A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG +SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY +bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ +JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm +epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN +F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF +MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f +hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo +bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs +afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM +PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD +KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 +QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE-----`)) + + //DigiCert Assured ID Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx +MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO +9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy +UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW +/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy +oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf +GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF +66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq +hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc +EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn +SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i +8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE-----`)) + + //DigiCert Global Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw +MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn +TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 +BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H +4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y +7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB +o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm +8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF +BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr +EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt +tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 +UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE-----`)) + + //DigiCert High Assurance EV Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw +KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw +MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ +MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu +Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t +Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS +OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 +MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ +NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe +h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB +Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY +JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ +V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp +myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK +mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K +-----END CERTIFICATE-----`)) + + //SwissSign Gold CA - G2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw +EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN +MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp +c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq +t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C +jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg +vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF +ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR +AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend +jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO +peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR +7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi +GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 +OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm +5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr +44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf +Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m +Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp +mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk +vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf +KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br +NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj +viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----END CERTIFICATE-----`)) + + //SwissSign Silver CA - G2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT +BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X +DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3 +aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG +9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644 +N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm ++/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH +6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu +MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h +qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5 +FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs +ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc +celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X +CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB +tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 +cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P +4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F +kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L +3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx +/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa +DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP +e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu +WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ +DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub +DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u +-----END CERTIFICATE-----`)) + + //SecureTrust CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy +dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe +BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX +OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t +DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH +GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b +01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH +ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj +aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu +SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf +mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ +nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE-----`)) + + //Secure Global CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH +bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg +MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg +Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx +YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ +bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g +8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV +HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi +0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn +oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA +MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ +OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn +CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 +3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE-----`)) + + //COMODO Certification Authority + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb +MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD +T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH ++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww +xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV +4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA +1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI +rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k +b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC +AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP +OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc +IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN ++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== +-----END CERTIFICATE-----`)) + + //COMODO ECC Certification Authority + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix +GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X +4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni +wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG +FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA +U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE-----`)) + + //Certigna + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw +EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 +MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI +Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q +XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH +GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p +ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg +DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf +Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ +tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ +BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J +SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA +hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ +ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu +PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY +1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE-----`)) + + //ePKI Root Certification Authority + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx +MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq +MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs +IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi +lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv +qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX +12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O +WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ +ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao +lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ +vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi +Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi +MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 +1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq +KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV +xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP +NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r +GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE +xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx +gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy +sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD +BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE-----`)) + + //certSIGN ROOT CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD +VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa +Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE +CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I +JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH +rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 +ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD +0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 +AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B +Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB +AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 +SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 +x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt +vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz +TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD +-----END CERTIFICATE-----`)) + + //NetLock Arany (Class Gold) Főtanúsítvány + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G +A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 +dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB +cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx +MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO +ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 +c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu +0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw +/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk +H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw +fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 +neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW +qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta +YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna +NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu +dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE-----`)) + + //SecureSign RootCA11 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi +SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS +b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw +KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 +cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL +TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO +wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq +g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP +O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA +bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX +t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh +OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r +bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ +Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 +y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 +lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE-----`)) + + //Microsec e-Szigno Root CA 2009 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER +MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv +c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE +BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt +U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA +fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG +0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA +pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm +1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC +AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf +QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE +FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o +lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX +I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 +yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi +LXpUq3DDfSJlgnCW +-----END CERTIFICATE-----`)) + + //GlobalSign Root CA - R3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt +iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ +0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 +rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl +OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 +xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 +lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 +EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E +bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 +YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r +kpeDMdmztcpHWD9f +-----END CERTIFICATE-----`)) + + //Autoridad de Certificacion Firmaprofesional CIF A62634068 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud +EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH +DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA +bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx +ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx +51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk +R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP +T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f +Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl +osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR +crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR +saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD +KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi +6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE-----`)) + + //Izenpe.com + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG +EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz +MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu +QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ +03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK +ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU ++zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC +PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT +OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK +F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK +0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+ +0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB +leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID +AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+ +SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG +NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l +Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga +kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q +hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs +g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5 +aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5 +nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC +ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo +Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z +WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----END CERTIFICATE-----`)) + + //Go Daddy Root Certificate Authority - G2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu +MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G +A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq +9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD ++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd +fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl +NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 +BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac +vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r +5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV +N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 +-----END CERTIFICATE-----`)) + + //Starfield Root Certificate Authority - G2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 +eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw +DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg +VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB +dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv +W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs +bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk +N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf +ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU +JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol +TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx +4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw +F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ +c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE-----`)) + + //Starfield Services Root Certificate Authority - G2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl +IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT +dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 +h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa +hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP +LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB +rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG +SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP +E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy +xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza +YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 +-----END CERTIFICATE-----`)) + + //AffirmTrust Commercial + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw +MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb +DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV +C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 +BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww +MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV +HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG +hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi +qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv +0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh +sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE-----`)) + + //AffirmTrust Networking + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw +MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE +Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI +dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 +/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb +h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV +HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu +UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 +12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 +WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 +/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE-----`)) + + //AffirmTrust Premium + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy +OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy +dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn +BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV +5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs ++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd +GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R +p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI +S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 +6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 +/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo ++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv +MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC +6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S +L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK ++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV +BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg +IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 +g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb +zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== +-----END CERTIFICATE-----`)) + + //AffirmTrust Premium ECC + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV +BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx +MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U +cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ +N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW +BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK +BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X +57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM +eQ== +-----END CERTIFICATE-----`)) + + //Certum Trusted Network CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK +ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy +MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU +ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC +l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J +J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 +fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 +cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB +Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw +DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj +jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 +mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj +Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE-----`)) + + //TWCA Root Certification Authority + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ +VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG +EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB +IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx +QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC +oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP +4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r +y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG +9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC +mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW +QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY +T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny +Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE-----`)) + + //Security Communication RootCA2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh +dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC +SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy +aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ ++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R +3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV +spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K +EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 +QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB +CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj +u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk +3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q +tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 +mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE-----`)) + + //Actalis Authentication Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM +BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE +AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky +MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz +IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ +wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa +by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 +zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f +YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 +oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l +EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 +hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 +EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 +jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY +iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI +WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 +JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx +K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ +Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC +4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo +2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz +lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem +OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 +vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE-----`)) + + //Buypass Class 2 Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X +DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 +g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn +9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b +/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU +CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff +awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI +zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn +Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX +Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs +M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI +osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S +aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd +DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD +LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 +oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC +wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS +CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN +rJgWVqA= +-----END CERTIFICATE-----`)) + + //Buypass Class 3 Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X +DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH +sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR +5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh +7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ +ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH +2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV +/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ +RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA +Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq +j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G +uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG +Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 +ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 +KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz +6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug +UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe +eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi +Cp/HuZc= +-----END CERTIFICATE-----`)) + + //T-TeleSec GlobalRoot Class 3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx +MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK +9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU +NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF +iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W +0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr +AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb +fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT +ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h +P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== +-----END CERTIFICATE-----`)) + + //D-TRUST Root Class 3 CA 2 2009 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe +Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE +LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD +ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA +BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv +KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z +p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC +AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ +4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y +eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw +MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G +PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw +OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm +2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV +dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph +X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE-----`)) + + //D-TRUST Root Class 3 CA 2 EV 2009 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS +egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh +zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T +7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 +sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 +11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv +cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v +ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El +MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp +b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh +c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ +PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX +ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA +NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv +w9y4AyHqnxbxLFS1 +-----END CERTIFICATE-----`)) + + //CA Disig Root R2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw +EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp +ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx +EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp +c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC +w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia +xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 +A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S +GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV +g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa +5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE +koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A +Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i +Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u +Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV +sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je +dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 +1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx +mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 +utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 +sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg +UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV +7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE-----`)) + + //ACCVRAIZ1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB +SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 +MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH +UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM +jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 +RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD +aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ +0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG +WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 +8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR +5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J +9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK +Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw +Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu +Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM +Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA +QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh +AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA +YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj +AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA +IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk +aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 +dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 +MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI +hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E +R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN +YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 +nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ +TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 +sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg +Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd +3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p +EfbRD0tVNEYqi4Y7 +-----END CERTIFICATE-----`)) + + //TWCA Global Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT +CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD +QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK +EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg +Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C +nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV +r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR +Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV +tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W +KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 +sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p +yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn +kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI +zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g +cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M +8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg +/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg +lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP +A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m +i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 +EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 +zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= +-----END CERTIFICATE-----`)) + + //TeliaSonera Root CA v1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE +CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 +MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW +VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ +6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA +3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k +B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn +Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH +oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 +F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ +oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 +gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc +TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB +AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW +DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm +zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW +pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV +G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc +c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT +JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 +qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 +Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems +WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE-----`)) + + //T-TeleSec GlobalRoot Class 2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx +MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ +SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F +vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 +2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV +WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy +YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 +r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf +vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR +3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== +-----END CERTIFICATE-----`)) + + //Atos TrustedRoot 2011 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU +cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 +MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG +A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV +hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr +54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ +DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 +HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR +z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R +l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ +bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h +k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh +TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 +61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G +3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE-----`)) + + //QuoVadis Root CA 1 G3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE +PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm +PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6 +Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN +ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l +g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV +7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX +9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f +iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg +t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI +hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3 +GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct +Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP ++V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh +3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa +wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6 +O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0 +FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV +hMJKzRwuJIczYOXD +-----END CERTIFICATE-----`)) + + //QuoVadis Root CA 2 G3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh +ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY +NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t +oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o +MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l +V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo +L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ +sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD +6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh +lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI +hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K +pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9 +x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz +dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X +U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw +mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD +zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN +JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr +O3jtZsSOeWmD3n+M +-----END CERTIFICATE-----`)) + + //QuoVadis Root CA 3 G3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286 +IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL +Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe +6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3 +I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U +VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7 +5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi +Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM +dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt +rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI +hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS +t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ +TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du +DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib +Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD +hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX +0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW +dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2 +PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE-----`)) + + //DigiCert Assured ID Root G2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw +MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH +35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq +bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw +VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP +YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn +lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO +w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv +0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz +d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW +hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M +jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE-----`)) + + //DigiCert Assured ID Root G3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD +VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb +RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs +KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF +UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy +YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy +1vUhZscv6pZjamVFkpUBtA== +-----END CERTIFICATE-----`)) + + //DigiCert Global Root G2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx +MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ +kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO +3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV +BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM +UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB +o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu +5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr +F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U +WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH +QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/ +iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE-----`)) + + //DigiCert Global Root G3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD +VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw +MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k +aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C +AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O +YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp +Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y +3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34 +VOKa5Vt8sycX +-----END CERTIFICATE-----`)) + + //DigiCert Trusted Root G4 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw +HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp +pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o +k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa +vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY +QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 +MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm +mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7 +f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH +dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8 +oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY +ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr +yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy +7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah +ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN +5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb +/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa +5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK +G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP +82Z+ +-----END CERTIFICATE-----`)) + + //COMODO RSA Certification Authority + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn +dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ +FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+ +5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG +x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX +2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL +OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3 +sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C +GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5 +WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt +rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+ +nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg +tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW +sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp +pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA +zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq +ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52 +7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I +LaZRfyHBNVOFBkpdn627G190 +-----END CERTIFICATE-----`)) + + //USERTrust RSA Certification Authority + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE +BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK +ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE +BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK +ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz +0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j +Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn +RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O ++T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq +/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE +Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM +lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8 +yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+ +eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd +BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW +FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ +7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ +Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM +8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi +FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi +yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c +J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw +sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx +Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE-----`)) + + //USERTrust ECC Certification Authority + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2 +0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez +nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV +HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB +HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu +9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE-----`)) + + //GlobalSign ECC Root CA - R5 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6 +SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS +h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx +uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 +yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE-----`)) + + //IdenTrust Commercial Root CA 1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS +b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES +MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB +IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld +hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/ +mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi +1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C +XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl +3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy +NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV +WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg +xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix +uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI +hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg +ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt +ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV +YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX +feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro +kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe +2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz +Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R +cGzM7vRX+Bi6hG6H +-----END CERTIFICATE-----`)) + + //IdenTrust Public Sector Root CA 1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv +ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV +UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS +b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy +P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6 +Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI +rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf +qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS +mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn +ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh +LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v +iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL +4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B +Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw +DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A +mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt +GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt +m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx +NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4 +Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI +ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC +ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ +3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE-----`)) + + //Entrust Root Certification Authority - G2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy +bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug +b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw +HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT +DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx +OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP +/vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz +HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU +s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y +TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx +AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6 +0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z +iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi +nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+ +vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO +e4pIb4tF9g== +-----END CERTIFICATE-----`)) + + //Entrust Root Certification Authority - EC1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx +FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn +YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw +FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs +LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg +dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt +IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy +AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef +9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h +vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8 +kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE-----`)) + + //CFCA EV ROOT + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE +CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB +IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw +MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD +DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV +BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD +7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN +uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW +ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7 +xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f +py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K +gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol +hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ +tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf +BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q +ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua +4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG +E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX +BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn +aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy +PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX +kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C +ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE-----`)) + + //OISTE WISeKey Global Root GB CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG +EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw +MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds +b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX +scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP +rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk +9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o +Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg +GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI +hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD +dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0 +VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui +HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE-----`)) + + //SZAFIR ROOT CA2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG +A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV +BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ +BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD +VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q +qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK +DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE +2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ +ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi +ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC +AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 +O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 +oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul +4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 ++/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE-----`)) + + //Certum Trusted Network CA 2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE +BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 +bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y +ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ +TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB +IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 +7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o +CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b +Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p +uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 +GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ +9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB +Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye +hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM +BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI +hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW +Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA +L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo +clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM +pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb +w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo +J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm +ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX +is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 +zAYspsbiDrW5viSP +-----END CERTIFICATE-----`)) + + //Hellenic Academic and Research Institutions RootCA 2015 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT +BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0 +aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl +YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx +MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg +QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV +BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw +MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv +bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh +iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+ +6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd +FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr +i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F +GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2 +fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu +iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI +hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+ +D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM +d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y +d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn +82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb +davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F +Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt +J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa +JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q +p/UsQu0yrbYhnr68 +-----END CERTIFICATE-----`)) + + //Hellenic Academic and Research Institutions ECC RootCA 2015 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0 +aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u +cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj +aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw +MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj +IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD +VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290 +Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP +dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK +Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA +GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn +dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE-----`)) + + //ISRG Root X1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE +BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD +EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG +EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT +DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r +Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1 +3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K +b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN +Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ +4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf +1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu +hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH +usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r +OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G +A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY +9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV +0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt +hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw +TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx +e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA +JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD +YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n +JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ +m+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE-----`)) + + //AC RAIZ FNMT-RCM + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT +AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw +MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD +TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf +qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr +btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL +j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou +08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw +WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT +tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ +47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC +ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa +i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o +dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s +D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ +j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT +Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW ++YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7 +Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d +8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm +5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG +rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE-----`)) + + //Amazon Root CA 1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1 +MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH +FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ +gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t +dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce +VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3 +DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM +CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy +8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa +2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2 +xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE-----`)) + + //Amazon Root CA 2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1 +MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4 +kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp +N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9 +AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd +fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx +kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS +btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0 +Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN +c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+ +3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw +DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA +A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE +YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW +xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ +gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW +aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV +Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3 +KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi +JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw= +-----END CERTIFICATE-----`)) + + //Amazon Root CA 3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB +f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr +Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43 +rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc +eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw== +-----END CERTIFICATE-----`)) + + //Amazon Root CA 4 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN +/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri +83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA +MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1 +AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE-----`)) + + //TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT +D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr +IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g +TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp +ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD +VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt +c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth +bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11 +IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8 +6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc +wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0 +3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9 +WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU +ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc +lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R +e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j +q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= +-----END CERTIFICATE-----`)) + + //GDCA TrustAUTH R5 ROOT + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw +BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD +DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow +YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs +AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p +OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr +pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ +9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ +xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM +R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ +D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4 +oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx +9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9 +H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35 +6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd ++PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ +HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD +F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ +8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv +/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT +aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE-----`)) + + //SSL.com Root Certification Authority RSA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM +BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x +MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw +MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx +EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM +LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C +Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8 +P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge +oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp +k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z +fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ +gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2 +UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8 +1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s +bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr +dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf +ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl +u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq +erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj +MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ +vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI +Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y +wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI +WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE-----`)) + + //SSL.com Root Certification Authority ECC + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV +BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv +BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy +MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO +BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+ +8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR +hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT +jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW +e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z +5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE-----`)) + + //SSL.com EV Root Certification Authority RSA R2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w +DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u +MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI +DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD +VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh +hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w +cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO +Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+ +B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh +CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim +9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto +RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm +JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48 ++qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp +qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1 +++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx +Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G +guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz +OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7 +CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq +lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR +rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1 +hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX +9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE-----`)) + + //SSL.com EV Root Certification Authority ECC + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV +BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy +BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw +MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx +EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM +LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy +3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O +BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe +5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ +N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm +m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE-----`)) + + //GlobalSign Root CA - R6 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX +R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i +YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs +U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss +grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE +3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF +vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM +PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+ +azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O +WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy +CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP +0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN +b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV +HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0 +lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY +BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym +Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr +3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1 +0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T +uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK +oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t +JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE-----`)) + + //OISTE WISeKey Global Root GC CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD +SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo +MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa +Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL +ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr +VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab +NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E +AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk +AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE-----`)) + + //UCA Global G2 Root + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG +EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x +NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU +cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT +oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV +8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS +h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o +LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/ +R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe +KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa +4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc +OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97 +8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo +5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A +Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9 +yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX +c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo +jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk +bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x +ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn +RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A== +-----END CERTIFICATE-----`)) + + //UCA Extended Validation Root + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG +EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u +IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G +A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs +iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF +Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu +eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR +59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH +0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR +el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv +B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth +WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS +NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS +3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL +BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM +aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4 +dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb ++7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW +F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi +GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc +GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi +djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr +dhh2n1ax +-----END CERTIFICATE-----`)) + + //Certigna Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE +BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ +MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda +MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz +MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX +stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz +KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8 +JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16 +XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq +4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej +wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ +lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI +jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/ +/TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy +dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h +LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl +cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt +OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP +TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq +7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3 +4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd +8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS +6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY +tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS +aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde +E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE-----`)) + + //emSign Root CA - G1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET +MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl +ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx +ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk +aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN +LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1 +cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW +DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ +6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH +hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG +MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2 +vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q +NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q ++Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih +U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx +iN66zB+Afko= +-----END CERTIFICATE-----`)) + + //emSign ECC Root CA - G3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG +A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg +MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4 +MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11 +ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g +RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc +58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr +MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D +CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7 +jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj +-----END CERTIFICATE-----`)) + + //emSign Root CA - C1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx +EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp +Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE +BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD +ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up +ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/ +Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX +OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V +I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms +lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+ +XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD +ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp +/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1 +NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9 +wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ +BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI= +-----END CERTIFICATE-----`)) + + //emSign ECC Root CA - C3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG +A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF +Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE +BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD +ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd +6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9 +SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA +B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA +MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU +ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== +-----END CERTIFICATE-----`)) + + //Hongkong Post Root CA 3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG +A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK +Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2 +MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv +bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX +SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz +iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf +jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim +5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe +sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj +0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/ +JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u +y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h ++bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG +xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID +AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e +i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN +AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw +W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld +y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov ++BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc +eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw +9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7 +nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY +hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB +60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq +dBb9HxEGmpv0 +-----END CERTIFICATE-----`)) + + //Entrust Root Certification Authority - G4 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV +BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu +bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1 +dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT +AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D +umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV +3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds +8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ +e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7 +ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X +xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV +7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 +dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW +Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n +MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q +jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht +7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK +YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt +jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+ +m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW +RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA +JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G ++TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT +kcpG2om3PVODLAgfi49T3f+sHw== +-----END CERTIFICATE-----`)) + + //Microsoft ECC Root Certificate Authority 2017 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV +UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND +IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4 +MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw +NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6 +thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB +eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM ++Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf +Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR +eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= +-----END CERTIFICATE-----`)) + + //Microsoft RSA Root Certificate Authority 2017 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG +EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg +UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw +NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u +MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml +7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e +S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7 +1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+ +dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F +yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS +MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr +lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ +0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ +ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og +6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80 +dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk ++ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex +/2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy +AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW +ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE +7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT +c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D +5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E +-----END CERTIFICATE-----`)) + + //e-Szigno Root CA 2017 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw +DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt +MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa +Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE +CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp +Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx +s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G +A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv +vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA +tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO +svxyqltZ+efcMQ== +-----END CERTIFICATE-----`)) + + //certSIGN Root CA G2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw +EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy +MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH +TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05 +N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk +abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg +wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp +dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh +ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732 +jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf +95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc +z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL +iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud +DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB +ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC +b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB +/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5 +8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5 +BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW +atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU +Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M +NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N +0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc= +-----END CERTIFICATE-----`)) + + //Trustwave Global Certification Authority + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV +UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 +ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTAeFw0xNzA4MjMxOTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJV +UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 +ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALldUShLPDeS0YLOvR29 +zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0XznswuvCAAJWX/NKSqIk4cXGIDtiLK0thAf +LdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4Bq +stTnoApTAbqOl5F2brz81Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9o +WN0EACyW80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotPJqX+ +OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1lRtzuzWniTY+HKE40 +Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfwhI0Vcnyh78zyiGG69Gm7DIwLdVcE +uE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm ++9jaJXLE9gCxInm943xZYkqcBW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqj +ifLJS3tBEW1ntwiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1UdDwEB/wQEAwIB +BjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W0OhUKDtkLSGm+J1WE2pIPU/H +PinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfeuyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0H +ZJDmHvUqoai7PF35owgLEQzxPy0QlG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla +4gt5kNdXElE1GYhBaCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5R +vbbEsLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPTMaCm/zjd +zyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qequ5AvzSxnI9O4fKSTx+O +856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxhVicGaeVyQYHTtgGJoC86cnn+OjC/QezH +Yj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu +3R3y4G5OBVixwJAWKqQ9EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP +29FpHOTKyeC2nOnOcXHebD8WpHk= +-----END CERTIFICATE-----`)) + + //Trustwave Global ECC P256 Certification Authority + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER +MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy +dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1 +NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj +43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm +P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt +0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz +RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 +-----END CERTIFICATE-----`)) + + //Trustwave Global ECC P384 Certification Authority + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER +MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy +dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4 +NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH +Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr +/TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV +HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn +ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl +CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw== +-----END CERTIFICATE-----`)) + + //NAVER Global Root Certification Authority + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG +A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD +DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4 +NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT +UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb +UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW ++j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7 +XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2 +aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4 +Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z +VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B +A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai +cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy +YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV +HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK +21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB +jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx +hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg +E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH +D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ +A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY +qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG +I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg +kpzNNIaRkPpkUZ3+/uul9XXeifdy +-----END CERTIFICATE-----`)) + + //AC RAIZ FNMT-RCM SERVIDORES SEGUROS + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQswCQYDVQQGEwJF +UzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgwFgYDVQRhDA9WQVRFUy1RMjgy +NjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1SQ00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4 +MTIyMDA5MzczM1oXDTQzMTIyMDA5MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQt +UkNNMQ4wDAYDVQQLDAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNB +QyBSQUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LHsbI6GA60XYyzZl2hNPk2 +LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oKUm8BA06Oi6NCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqG +SM49BAMDA2kAMGYCMQCuSuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoD +zBOQn5ICMQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJyv+c= +-----END CERTIFICATE-----`)) + + //GlobalSign Root R46 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUAMEYxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJv +b3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAX +BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08Es +CVeJOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQGvGIFAha/ +r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud316HCkD7rRlr+/fKYIje +2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo0q3v84RLHIf8E6M6cqJaESvWJ3En7YEt +bWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSEy132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvj +K8Cd+RTyG/FWaha/LIWFzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD4 +12lPFzYE+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCNI/on +ccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzsx2sZy/N78CsHpdls +eVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqaByFrgY/bxFn63iLABJzjqls2k+g9 +vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEM +BQADggIBAHx47PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg +JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti2kM3S+LGteWy +gxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIkpnnpHs6i58FZFZ8d4kuaPp92 +CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRFFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZm +OUdkLG5NrmJ7v2B0GbhWrJKsFjLtrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qq +JZ4d16GLuc1CLgSkZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwye +qiv5u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP4vkYxboz +nxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6N3ec592kD3ZDZopD8p/7 +DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3vouXsXgxT7PntgMTzlSdriVZzH81Xwj3 +QEUxeCp6 +-----END CERTIFICATE-----`)) + + //GlobalSign Root E46 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYxCzAJBgNVBAYT +AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJvb3Qg +RTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNV +BAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkB +jtjqR+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGddyXqBPCCj +QjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQxCpCPtsad0kRL +gLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZk +vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+ +CAezNIm8BZ/3Hobui3A= +-----END CERTIFICATE-----`)) + + //GLOBALTRUST 2020 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx +IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT +VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh +BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy +MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi +D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO +VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM +CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm +fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA +A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR +JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG +DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU +clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ +mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud +IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA +VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw +4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9 +iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS +8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2 +HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS +vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918 +oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF +YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl +gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== +-----END CERTIFICATE-----`)) + + //ANF Secure Server Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNVBAUTCUc2MzI4 +NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lv +bjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNVBAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3Qg +Q0EwHhcNMTkwOTA0MTAwMDM4WhcNMzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEw +MQswCQYDVQQGEwJFUzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQw +EgYDVQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9vdCBDQTCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCjcqQZAZ2cC4Ffc0m6p6zz +BE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9qyGFOtibBTI3/TO80sh9l2Ll49a2pcbnv +T1gdpd50IJeh7WhM3pIXS7yr/2WanvtH2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcv +B2VSAKduyK9o7PQUlrZXH1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXse +zx76W0OLzc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyRp1RM +VwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQzW7i1o0TJrH93PB0j +7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/SiOL9V8BY9KHcyi1Swr1+KuCLH5z +JTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJnLNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe +8TZBAQIvfXOn3kLMTOmJDVb3n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVO +Hj1tyRRM4y5Bu8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj +o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAOBgNVHQ8BAf8E +BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEATh65isagmD9uw2nAalxJ +UqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzx +j6ptBZNscsdW699QIyjlRRA96Gejrw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDt +dD+4E5UGUcjohybKpFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM +5gf0vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjqOknkJjCb +5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ/zo1PqVUSlJZS2Db7v54 +EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ92zg/LFis6ELhDtjTO0wugumDLmsx2d1H +hk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI+PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGy +g77FGr8H6lnco4g175x2MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3 +r5+qPeoott7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw= +-----END CERTIFICATE-----`)) + + //Certum EC-384 CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQswCQYDVQQGEwJQ +TDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2 +MDcyNDU0WhcNNDMwMzI2MDcyNDU0WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERh +dGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx +GTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATEKI6rGFtq +vm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7TmFy8as10CW4kjPMIRBSqn +iBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68KjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFI0GZnQkdjrzife81r1HfS+8EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNo +ADBlAjADVS2m5hjEfO/JUG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0 +QoSZ/6vnnvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= +-----END CERTIFICATE-----`)) + + //Certum Trusted Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6MQswCQYDVQQG +EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0g +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0Ew +HhcNMTgwMzE2MTIxMDEzWhcNNDMwMzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMY +QXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZn0EGze2jusDbCSzBfN8p +fktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/qp1x4EaTByIVcJdPTsuclzxFUl6s1wB52 +HO8AU5853BSlLCIls3Jy/I2z5T4IHhQqNwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2 +fJmItdUDmj0VDT06qKhF8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGt +g/BKEiJ3HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGamqi4 +NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi7VdNIuJGmj8PkTQk +fVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSFytKAQd8FqKPVhJBPC/PgP5sZ0jeJ +P/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0PqafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSY +njYJdmZm/Bo/6khUHL4wvYBQv3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHK +HRzQ+8S1h9E6Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1 +vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQADggIBAEii1QAL +LtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4WxmB82M+w85bj/UvXgF2Ez8s +ALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvozMrnadyHncI013nR03e4qllY/p0m+jiGPp2K +h2RX5Rc64vmNueMzeMGQ2Ljdt4NR5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8 +CYyqOhNf6DR5UMEQGfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA +4kZf5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq0Uc9Nneo +WWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7DP78v3DSk+yshzWePS/Tj +6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTMqJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmT +OPQD8rv7gmsHINFSH5pkAnuYZttcTVoP0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZck +bxJF0WddCajJFdr60qZfE2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb +-----END CERTIFICATE-----`)) + + //TunTrust Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQELBQAwYTELMAkG +A1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUgQ2VydGlmaWNhdGlvbiBFbGVj +dHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJvb3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQw +NDI2MDg1NzU2WjBhMQswCQYDVQQGEwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBD +ZXJ0aWZpY2F0aW9uIEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZn56eY+hz +2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd2JQDoOw05TDENX37Jk0b +bjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgFVwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7 +NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZGoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAd +gjH8KcwAWJeRTIAAHDOFli/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViW +VSHbhlnUr8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2eY8f +Tpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIbMlEsPvLfe/ZdeikZ +juXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISgjwBUFfyRbVinljvrS5YnzWuioYas +DXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwS +VXAkPcvCFDVDXSdOvsC9qnyW5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI +04Y+oXNZtPdEITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 +90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+zxiD2BkewhpMl +0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYuQEkHDVneixCwSQXi/5E/S7fd +Ao74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRY +YdZ2vyJ/0Adqp2RT8JeNnYA/u8EH22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJp +adbGNjHh/PqAulxPxOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65x +xBzndFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5Xc0yGYuP +jCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7bnV2UqL1g52KAdoGDDIzM +MEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQCvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9z +ZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZHu/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3r +AZ3r2OvEhJn7wAzMMujjd9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= +-----END CERTIFICATE-----`)) + + //HARICA TLS RSA Root CA 2021 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG +EwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u +cyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0EgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUz +OFoXDTQ1MDIxMzEwNTUzN1owbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRl +bWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNB +IFJvb3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569lmwVnlskN +JLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE4VGC/6zStGndLuwRo0Xu +a2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uva9of08WRiFukiZLRgeaMOVig1mlDqa2Y +Ulhu2wr7a89o+uOkXjpFc5gH6l8Cct4MpbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K +5FrZx40d/JiZ+yykgmvwKh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEv +dmn8kN3bLW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcYAuUR +0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqBAGMUuTNe3QvboEUH +GjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYqE613TBoYm5EPWNgGVMWX+Ko/IIqm +haZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHrW2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQ +CPxrvrNQKlr9qEgYRtaQQJKQCoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAUX15QvWiWkKQU +EapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3f5Z2EMVGpdAgS1D0NTsY9FVq +QRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxajaH6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxD +QpSbIPDRzbLrLFPCU3hKTwSUQZqPJzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcR +j88YxeMn/ibvBZ3PzzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5 +vZStjBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0/L5H9MG0 +qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pTBGIBnfHAT+7hOtSLIBD6 +Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79aPib8qXPMThcFarmlwDB31qlpzmq6YR/ +PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YWxw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnn +kf3/W9b3raYvAwtt41dU63ZTGI0RmLo= +-----END CERTIFICATE-----`)) + + //HARICA TLS ECC Root CA 2021 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQswCQYDVQQGEwJH +UjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBD +QTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoX +DTQ1MDIxMzExMDEwOVowbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWlj +IGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJv +b3QgQ0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7KKrxcm1l +AEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9YSTHMmE5gEYd103KUkE+b +ECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW +0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAi +rcJRQO9gcS3ujwLEXQNwSaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/Qw +CZ61IygNnxS2PFOiTAZpffpskcYqSUXm7LcT4Tps +-----END CERTIFICATE-----`)) + + //Autoridad de Certificacion Firmaprofesional CIF A62634068 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1Ud +DgQWBBRlzeurNR4APn7VdMActHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4w +gZswgZgGBFUdIAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j +b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABCAG8AbgBhAG4A +bwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAwADEANzAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9miWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL +4QjbEwj4KKE1soCzC1HA01aajTNFSa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDb +LIpgD7dvlAceHabJhfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1il +I45PVf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZEEAEeiGaP +cjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV1aUsIC+nmCjuRfzxuIgA +LI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2tCsvMo2ebKHTEm9caPARYpoKdrcd7b/+A +lun4jWq9GJAd/0kakFI3ky88Al2CdgtR5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH +9IBk9W6VULgRfhVwOEqwf9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpf +NIbnYrX9ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNKGbqE +ZycPvEJdvSRUDewdcAZfpLz6IHxV +-----END CERTIFICATE-----`)) + + //vTrus ECC Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMwRzELMAkGA1UE +BhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBS +b290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDczMTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAa +BgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYw +EAYHKoZIzj0CAQYFK4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+c +ToL0v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUde4BdS49n +TPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIwV53dVvHH4+m4SVBrm2nDb+zDfSXkV5UT +QJtS0zvzQBm8JsctBp61ezaf9SXUY2sAAjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQL +YgmRWAD5Tfs0aNoJrSEGGJTO +-----END CERTIFICATE-----`)) + + //vTrus Root CA + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQELBQAwQzELMAkG +A1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xFjAUBgNVBAMTDXZUcnVzIFJv +b3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMxMDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoG +A1UEChMTaVRydXNDaGluYSBDby4sTHRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZots +SKYcIrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykUAyyNJJrI +ZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+GrPSbcKvdmaVayqwlHeF +XgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z98Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KA +YPxMvDVTAWqXcoKv8R1w6Jz1717CbMdHflqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70 +kLJrxLT5ZOrpGgrIDajtJ8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2 +AXPKBlim0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZNpGvu +/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQUqqzApVg+QxMaPnu +1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHWOXSuTEGC2/KmSNGzm/MzqvOmwMVO +9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMBAAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYg +scasGrz2iTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOC +AgEAKbqSSaet8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd +nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1jbhd47F18iMjr +jld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvMKar5CKXiNxTKsbhm7xqC5PD4 +8acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIivTDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJn +xDHO2zTlJQNgJXtxmOTAGytfdELSS8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554Wg +icEFOwE30z9J4nfrI8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4 +sEb9b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNBUvupLnKW +nyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1PTi07NEPhmg4NpGaXutIc +SkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929vensBxXVsFy6K2ir40zSbofitzmdHxghm+H +l3s= +-----END CERTIFICATE-----`)) + + //ISRG Root X2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQswCQYDVQQGEwJV +UzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElT +UkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVT +MSkwJwYDVQQKEyBJbnRlcm5ldCBTZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNS +RyBSb290IFgyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0H +ttwW+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9ItgKbppb +d9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZIzj0EAwMDaAAwZQIwe3lORlCEwkSHRhtF +cP9Ymd70/aTSVaYgLXTWNLxBo1BfASdWtL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5 +U6VR5CmD1/iQMVtCnwr1/q4AaOeMSQ+2b1tbFfLn +-----END CERTIFICATE-----`)) + + //HiPKI Root CA - G1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xGzAZBgNVBAMMEkhpUEtJ +IFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRaFw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYT +AlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kg +Um9vdCBDQSAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0 +o9QwqNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twvVcg3Px+k +wJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6lZgRZq2XNdZ1AYDgr/SE +YYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnzQs7ZngyzsHeXZJzA9KMuH5UHsBffMNsA +GJZMoYFL3QRtU6M9/Aes1MU3guvklQgZKILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfd +hSi8MEyr48KxRURHH+CKFgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj +1jOXTyFjHluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDry+K4 +9a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ/W3c1pzAtH2lsN0/ +Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgMa/aOEmem8rJY5AIJEzypuxC00jBF +8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQD +AgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi +7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqcSE5XCV0vrPSl +tJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6FzaZsT0pPBWGTMpWmWSBUdGSquE +wx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9TcXzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07Q +JNBAsNB1CI69aO4I1258EHBGG3zgiLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv +5wiZqAxeJoBF1PhoL5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+Gpz +jLrFNe85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wrkkVbbiVg +hUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+vhV4nYWBSipX3tUZQ9rb +yltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQUYDksswBVLuT1sw5XxJFBAJw/6KXf6vb/ +yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== +-----END CERTIFICATE-----`)) + + //GlobalSign ECC Root CA - R4 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYDVQQLExtHbG9i +YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgwMTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9i +YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkW +ymOxuYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNVHQ8BAf8E +BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/+wpu+74zyTyjhNUwCgYI +KoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147bmF0774BxL4YSFlhgjICICadVGNA3jdg +UM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm +-----END CERTIFICATE-----`)) + + //GTS Root R1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM +f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7raKb0 +xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnWr4+w +B7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXW +nOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk +9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zq +kUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92wO1A +K/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om3xPX +V2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDW +cfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQAD +ggIBAJ+qQibbC5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe +QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuyh6f88/qBVRRi +ClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM47HLwEXWdyzRSjeZ2axfG34ar +J45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8JZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYci +NuaCp+0KueIHoI17eko8cdLiA6EfMgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5me +LMFrUKTX5hgUvYU/Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJF +fbdT6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ0E6yove+ +7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm2tIMPNuzjsmhDYAPexZ3 +FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bbbP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3 +gm3c +-----END CERTIFICATE-----`)) + + //GTS Root R2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv +CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo7JUl +e3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWIm8Wb +a96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS ++LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7M +kogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJG +r61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RWIr9q +S34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73VululycslaVNV +J1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy5okL +dWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQAD +ggIBAB/Kzt3HvqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 +0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyCB19m3H0Q/gxh +swWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2uNmSRXbBoGOqKYcl3qJfEycel +/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMgyALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVn +jWQye+mew4K6Ki3pHrTgSAai/GevHyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y5 +9PYjJbigapordwj6xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M +7YNRTOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924SgJPFI/2R8 +0L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV7LXTWtiBmelDGDfrs7vR +WGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjW +HYbL +-----END CERTIFICATE-----`)) + + //GTS Root R3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi +MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMw +HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ +R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjO +PQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout +736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24CejQjBA +MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP0/Eq +Er24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azT +L818+FsuVbu/3ZL3pAzcMeGiAjEA/JdmZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV +11RZt+cRLInUue4X +-----END CERTIFICATE-----`)) + + //GTS Root R4 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi +MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQw +HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ +R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjO +PQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu +hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqjQjBA +MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV2Py1 +PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/C +r8deVl5c1RxYIigL9zC2L7F8AjEA8GE8p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh +4rsUecrNIdSUtUlD +-----END CERTIFICATE-----`)) + + //Telia Root CA v2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNVBAYT +AkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2 +MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQK +DBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ7 +6zBqAMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9vVYiQJ3q +9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9lRdU2HhE8Qx3FZLgmEKn +pNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTODn3WhUidhOPFZPY5Q4L15POdslv5e2QJl +tI5c0BE0312/UqeBAMN/mUWZFdUXyApT7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW +5olWK8jjfN7j/4nlNW4o6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNr +RBH0pUPCTEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6WT0E +BXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63RDolUK5X6wK0dmBR4 +M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZIpEYslOqodmJHixBTB0hXbOKSTbau +BcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGjYzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7W +xy+G2CQ5MB0GA1UdDgQWBBRyrOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ +8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi0f6X+J8wfBj5 +tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMMA8iZGok1GTzTyVR8qPAs5m4H +eW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBSSRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+C +y748fdHif64W1lZYudogsYMVoe+KTTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygC +QMez2P2ccGrGKMOF6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15 +h2Er3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMtTy3EHD70 +sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pTVmBds9hCG1xLEooc6+t9 +xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAWysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQ +raVplI/owd8k+BsHMYeB2F326CjYSlKArBPuUBQemMc= +-----END CERTIFICATE-----`)) + + //D-TRUST BR Root CA 1 2020 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE +RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0EgMSAy +MDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNV +BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7 +dPYSzuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0QVK5buXu +QqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/VbNafAkl1bK6CKBrqx9t +MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu +bmV0L2NybC9kLXRydXN0X2JyX3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP +PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD +AwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFWwKrY7RjEsK70Pvom +AjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHVdWNbFJWcHwHP2NVypw87 +-----END CERTIFICATE-----`)) + + //D-TRUST EV Root CA 1 2020 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE +RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0EgMSAy +MDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNV +BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8 +ZRCC/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rDwpdhQntJ +raOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3OqQo5FD4pPfsazK2/umL +MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu +bmV0L2NybC9kLXRydXN0X2V2X3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP +PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD +AwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CAy/m0sRtW9XLS/BnR +AjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJbgfM0agPnIjhQW+0ZT0MW +-----END CERTIFICATE-----`)) + + //DigiCert TLS ECC P384 Root G5 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURpZ2lDZXJ0IFRMUyBFQ0MgUDM4 +NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQg +Um9vdCBHNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1Tzvd +lHJS7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp0zVozptj +n4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICISB4CIfBFqMA4GA1UdDwEB +/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQCJao1H5+z8blUD2Wds +Jk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQLgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIx +AJSdYsiJvRmEFOml+wG4DXZDjC5Ty3zfDBeWUA== +-----END CERTIFICATE-----`)) + + //DigiCert TLS RSA4096 Root G5 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBNMQswCQYDVQQG +EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0 +MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcNNDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2 +IFJvb3QgRzUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS8 +7IE+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG02C+JFvuU +AT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgpwgscONyfMXdcvyej/Ces +tyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZMpG2T6T867jp8nVid9E6P/DsjyG244gXa +zOvswzH016cpVIDPRFtMbzCe88zdH5RDnU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnV +DdXifBBiqmvwPXbzP6PosMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9q +TXeXAaDxZre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cdLvvy +z6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvXKyY//SovcfXWJL5/ +MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNeXoVPzthwiHvOAbWWl9fNff2C+MIk +wcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPLtgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4E +FgQUUTMc7TZArxfTJc1paPKvTiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw +GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7HPNtQOa27PShN +lnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLFO4uJ+DQtpBflF+aZfTCIITfN +MBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQREtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/ +u4cnYiWB39yhL/btp/96j1EuMPikAdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9G +OUrYU9DzLjtxpdRv/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh +47a+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilwMUc/dNAU +FvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WFqUITVuwhd4GTWgzqltlJ +yqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCKovfepEWFJqgejF0pW8hL2JpqA15w8oVP +bEtoL8pU9ozaMv7Da4M/OMZ+ +-----END CERTIFICATE-----`)) + + //Certainly Root R1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UE +BhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2VydGFpbmx5IFJvb3QgUjEwHhcN +MjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2Vy +dGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBANA21B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O +5MQTvqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbedaFySpvXl +8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b01C7jcvk2xusVtyWMOvwl +DbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGI +XsXwClTNSaa/ApzSRKft43jvRl5tcdF5cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkN +KPl6I7ENPT2a/Z2B7yyQwHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQ +AjeZjOVJ6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA2Cnb +rlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyHWyf5QBGenDPBt+U1 +VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMReiFPCyEQtkA6qyI6BJyLm4SGcprS +p6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBTgqj8ljZ9EXME66C6ud0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAsz +HQNTVfSVcOQrPbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d +8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi1wrykXprOQ4v +MMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrdrRT90+7iIgXr0PK3aBLXWopB +GsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9ditaY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+ +gjwN/KUD+nsa2UUeYNrEjvn8K8l7lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgH +JBu6haEaBQmAupVjyTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7 +fpYnKx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLyyCwzk5Iw +x06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5nwXARPbv0+Em34yaXOp/S +X3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6OV+KmalBWQewLK8= +-----END CERTIFICATE-----`)) + + //Certainly Root E1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQswCQYDVQQGEwJV +UzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBFMTAeFw0yMTA0 +MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlu +bHkxGjAYBgNVBAMTEUNlcnRhaW5seSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4 +fxzf7flHh4axpMCK+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9 +YBk2QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4hevIIgcwCgYIKoZIzj0E +AwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8 +rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR +-----END CERTIFICATE-----`)) + + //E-Tugra Global Root CA RSA v3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIF8zCCA9ugAwIBAgIUDU3FzRYilZYIfrgLfxUGNPt5EDQwDQYJKoZIhvcNAQELBQAwgYAxCzAJ +BgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAb +BgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290 +IENBIFJTQSB2MzAeFw0yMDAzMTgwOTA3MTdaFw00NTAzMTIwOTA3MTdaMIGAMQswCQYDVQQGEwJU +UjEPMA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRF +LVR1Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBSU0Eg +djMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCiZvCJt3J77gnJY9LTQ91ew6aEOErx +jYG7FL1H6EAX8z3DeEVypi6Q3po61CBxyryfHUuXCscxuj7X/iWpKo429NEvx7epXTPcMHD4QGxL +sqYxYdE0PD0xesevxKenhOGXpOhL9hd87jwH7eKKV9y2+/hDJVDqJ4GohryPUkqWOmAalrv9c/SF +/YP9f4RtNGx/ardLAQO/rWm31zLZ9Vdq6YaCPqVmMbMWPcLzJmAy01IesGykNz709a/r4d+ABs8q +QedmCeFLl+d3vSFtKbZnwy1+7dZ5ZdHPOrbRsV5WYVB6Ws5OUDGAA5hH5+QYfERaxqSzO8bGwzrw +bMOLyKSRBfP12baqBqG3q+Sx6iEUXIOk/P+2UNOMEiaZdnDpwA+mdPy70Bt4znKS4iicvObpCdg6 +04nmvi533wEKb5b25Y08TVJ2Glbhc34XrD2tbKNSEhhw5oBOM/J+JjKsBY04pOZ2PJ8QaQ5tndLB +eSBrW88zjdGUdjXnXVXHt6woq0bM5zshtQoK5EpZ3IE1S0SVEgpnpaH/WwAH0sDM+T/8nzPyAPiM +bIedBi3x7+PmBvrFZhNb/FAHnnGGstpvdDDPk1Po3CLW3iAfYY2jLqN4MpBs3KwytQXk9TwzDdbg +h3cXTJ2w2AmoDVf3RIXwyAS+XF1a4xeOVGNpf0l0ZAWMowIDAQABo2MwYTAPBgNVHRMBAf8EBTAD +AQH/MB8GA1UdIwQYMBaAFLK0ruYt9ybVqnUtdkvAG1Mh0EjvMB0GA1UdDgQWBBSytK7mLfcm1ap1 +LXZLwBtTIdBI7zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAImocn+M684uGMQQ +gC0QDP/7FM0E4BQ8Tpr7nym/Ip5XuYJzEmMmtcyQ6dIqKe6cLcwsmb5FJ+Sxce3kOJUxQfJ9emN4 +38o2Fi+CiJ+8EUdPdk3ILY7r3y18Tjvarvbj2l0Upq7ohUSdBm6O++96SmotKygY/r+QLHUWnw/q +ln0F7psTpURs+APQ3SPh/QMSEgj0GDSz4DcLdxEBSL9htLX4GdnLTeqjjO/98Aa1bZL0SmFQhO3s +SdPkvmjmLuMxC1QLGpLWgti2omU8ZgT5Vdps+9u1FGZNlIM7zR6mK7L+d0CGq+ffCsn99t2HVhjY +sCxVYJb6CH5SkPVLpi6HfMsg2wY+oF0Dd32iPBMbKaITVaA9FCKvb7jQmhty3QUBjYZgv6Rn7rWl +DdF/5horYmbDB7rnoEgcOMPpRfunf/ztAmgayncSd6YAVSgU7NbHEqIbZULpkejLPoeJVF3Zr52X +nGnnCv8PWniLYypMfUeUP95L6VPQMPHF9p5J3zugkaOj/s1YzOrfr28oO6Bpm4/srK4rVJ2bBLFH +IK+WEj5jlB0E5y67hscMmoi/dkfv97ALl2bSRM9gUgfh1SxKOidhd8rXj+eHDjD/DLsE4mHDosiX +YY60MGo8bcIHX0pzLz/5FooBZu+6kcpSV3uu1OYP3Qt6f4ueJiDPO++BcYNZ +-----END CERTIFICATE-----`)) + + //E-Tugra Global Root CA ECC v3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMwgYAxCzAJBgNV +BAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAbBgNV +BAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENB +IEVDQyB2MzAeFw0yMDAzMTgwOTQ2NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEP +MA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1 +Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBFQ0MgdjMw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQKczLWYHMjLiSF4mDKpL2 +w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YKfWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31 +Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQ +zPUwHQYDVR0OBBYEFP+CMXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO +PQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4W +Aie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3 +-----END CERTIFICATE-----`)) + + //Security Communication RootCA3 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNVBAYTAkpQMSUw +IwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQDEx5TZWN1cml0eSBD +b21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQsw +CQYDVQQGEwJKUDElMCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UE +AxMeU2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4rCmDvu20r +hvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzAlrenfna84xtSGc4RHwsE +NPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MGTfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2 +/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF79+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGm +npjKIG58u4iFW/vAEGK78vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtY +XLVqAvO4g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3weGVPK +p7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst+3A7caoreyYn8xrC +3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M0V9hvqG8OmpI6iZVIhZdXw3/JzOf +GAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQT9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0Vcw +CBEF/VfR2ccCAwEAAaNCMEAwHQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB +/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS +YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PAFNr0Y/Dq9HHu +Tofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd9XbXv8S2gVj/yP9kaWJ5rW4O +H3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQIUYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASx +YfQAW0q3nHE3GYV5v4GwxxMOdnE+OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZ +XSEIx2C/pHF7uNkegr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml ++LLfiAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUVnuiZIesn +KwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD2NCcnWXL0CsnMQMeNuE9 +dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI//1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm +6Vwdp6POXiUyK+OVrCoHzrQoeIY8LaadTdJ0MN1kURXbg4NR16/9M51NZg== +-----END CERTIFICATE-----`)) + + //Security Communication ECC RootCA1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUwIwYD +VQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21t +dW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYxNjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTEL +MAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNV +BAMTIlNlY3VyaXR5IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+CnnfdldB9sELLo +5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpKULGjQjBAMB0GA1UdDgQW +BBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAK +BggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3L +snNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70e +N9k= +-----END CERTIFICATE-----`)) + + //BJCA Global Root CA1 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQG +EwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJK +Q0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAzMTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkG +A1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQD +DBRCSkNBIEdsb2JhbCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFm +CL3ZxRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZspDyRhyS +sTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O558dnJCNPYwpj9mZ9S1Wn +P3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgRat7GGPZHOiJBhyL8xIkoVNiMpTAK+BcW +yqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRj +eulumijWML3mG90Vr4TqnMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNn +MoH1V6XKV0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/pj+b +OT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZOz2nxbkRs1CTqjSSh +GL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXnjSXWgXSHRtQpdaJCbPdzied9v3pK +H9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMB +AAGjQjBAMB0GA1UdDgQWBBTF7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 +YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3KliawLwQ8hOnThJ +dMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u+2D2/VnGKhs/I0qUJDAnyIm8 +60Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuh +TaRjAv04l5U/BXCga99igUOLtFkNSoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW +4AB+dAb/OMRyHdOoP2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmp +GQrI+pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRzznfSxqxx +4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9eVzYH6Eze9mCUAyTF6ps +3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4S +SPfSKcOYKMryMguTjClPPGAyzQWWYezyr/6zcCwupvI= +-----END CERTIFICATE-----`)) + + //BJCA Global Root CA2 + certs = append(certs, []byte(`-----BEGIN CERTIFICATE----- +MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQswCQYDVQQGEwJD +TjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJKQ0Eg +R2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgyMVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UE +BhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRC +SkNBIEdsb2JhbCBSb290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jl +SR9BIgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK++kpRuDCK +/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJKsVF/BvDRgh9Obl+rg/xI +1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8 +W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8g +UXOQwKhbYdDFUDn9hf7B43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== +-----END CERTIFICATE-----`)) + + return certs +} + +func rootCerts() *x509.CertPool { + roots := x509.NewCertPool() + raw := rawCerts() + for i := 0; i < len(raw); i++ { + ok := roots.AppendCertsFromPEM(raw[i]) + if !ok { + log.Error("%s", string(raw[i])) + panic("failed to parse root certificate") + } + } + + return roots +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/sslhelpers/ssl_helper.go b/wasm/mix-fetch/go-mix-conn/internal/sslhelpers/ssl_helper.go new file mode 100644 index 0000000000..97d118933b --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/sslhelpers/ssl_helper.go @@ -0,0 +1,15 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package sslhelpers + +import ( + "crypto/tls" +) + +func TlsConfig(serverName string) tls.Config { + return tls.Config{ + ServerName: serverName, + RootCAs: rootCerts(), + } +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/state/fake_connection.go b/wasm/mix-fetch/go-mix-conn/internal/state/fake_connection.go new file mode 100644 index 0000000000..b15841e209 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/state/fake_connection.go @@ -0,0 +1,307 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package state + +import ( + "bytes" + "crypto/tls" + "go-mix-conn/internal/bridge/rust_bridge" + "go-mix-conn/internal/log" + "go-mix-conn/internal/sslhelpers" + "go-mix-conn/internal/types" + "io" + "net" + "os" + "sync" + "time" +) + +// InjectedData is, well, the injected server data that came from the mixnet into this connection +type InjectedData struct { + ServerData <-chan []byte + //RemoteClosed <-chan bool + RemoteDone <-chan struct{} + + RemoteError <-chan error +} + +// ConnectionInjector controls data that goes over corresponding FakeConnection +type ConnectionInjector struct { + ServerData chan<- []byte + RemoteDone chan<- struct{} + //RemoteClosed chan<- bool + RemoteError chan<- error +} + +// FakeConnection is a type implementing net.Conn interface that allows us +// to inspect and control bytes that would normally go onto the wire +type FakeConnection struct { + requestId types.RequestId + remoteAddress string + data *InjectedData + + localDone chan struct{} + + readDeadline connDeadline + writeDeadline connDeadline + + pendingReads chan []byte +} + +// connDeadline is an abstraction for handling timeouts. +// source: https://github.com/golang/go/blob/release-branch.go1.20/src/net/pipe.go#L15 +type connDeadline struct { + mu sync.Mutex // Guards timer and cancel + timer *time.Timer + cancel chan struct{} // Must be non-nil +} + +func makeConnDeadline() connDeadline { + return connDeadline{cancel: make(chan struct{})} +} + +// set sets the point in time when the deadline will time out. +// A timeout event is signaled by closing the channel returned by waiter. +// Once a timeout has occurred, the deadline can be refreshed by specifying a +// t value in the future. +// +// A zero value for t prevents timeout. +// source: https://github.com/golang/go/blob/release-branch.go1.20/src/net/pipe.go#L31 +func (d *connDeadline) set(t time.Time) { + d.mu.Lock() + defer d.mu.Unlock() + + if d.timer != nil && !d.timer.Stop() { + <-d.cancel // Wait for the timer callback to finish and close cancel + } + d.timer = nil + + // Time is zero, then there is no deadline. + closed := isClosedChan(d.cancel) + if t.IsZero() { + if closed { + d.cancel = make(chan struct{}) + } + return + } + + // Time in the future, setup a timer to cancel in the future. + if dur := time.Until(t); dur > 0 { + if closed { + d.cancel = make(chan struct{}) + } + d.timer = time.AfterFunc(dur, func() { + close(d.cancel) + }) + return + } + + // Time in the past, so close immediately. + if !closed { + close(d.cancel) + } +} + +func (d *connDeadline) wait() chan struct{} { + d.mu.Lock() + defer d.mu.Unlock() + return d.cancel +} + +func isClosedChan(c <-chan struct{}) bool { + select { + case <-c: + return true + default: + return false + } +} + +// NewFakeConnection creates a new FakeConnection that implements net.Conn interface alongside +// handlers for injecting data into it +func NewFakeConnection(requestId types.RequestId, remoteAddress string) (*FakeConnection, ConnectionInjector) { + serverData := make(chan []byte, 10) + //remoteClosed := make(chan bool, 1) + remoteError := make(chan error, 1) + + localDone := make(chan struct{}) + remoteDone := make(chan struct{}) + + inj := ConnectionInjector{ + ServerData: serverData, + //RemoteClosed: remoteClosed, + RemoteDone: remoteDone, + RemoteError: remoteError, + } + + conn := &FakeConnection{ + data: &InjectedData{ + ServerData: serverData, + //RemoteClosed: remoteClosed, + RemoteDone: remoteDone, + RemoteError: remoteError, + }, + requestId: requestId, + remoteAddress: remoteAddress, + pendingReads: make(chan []byte, 1), + localDone: localDone, + readDeadline: makeConnDeadline(), + writeDeadline: makeConnDeadline(), + } + + return conn, inj +} + +// NewFakeTlsConn wraps a FakeConnection with all the TLS magic +// note: this returns a tls.Conn in the pre-handshake state +func NewFakeTlsConn(connectionId types.RequestId, remoteAddress string) (*tls.Conn, ConnectionInjector) { + host, _, err := net.SplitHostPort(remoteAddress) + if err != nil { + panic("todo") + } + conn, inj := NewFakeConnection(connectionId, remoteAddress) + tlsConfig := sslhelpers.TlsConfig(host) + tlsConn := tls.Client(conn, &tlsConfig) + return tlsConn, inj +} + +func (conn *FakeConnection) readAndBuffer(in []byte, out []byte) (int, error) { + buf := bytes.NewReader(in) + n, err := buf.Read(out) + + remaining := buf.Len() + if remaining > 0 { + leftover := make([]byte, remaining) + _, _ = buf.Read(leftover) + conn.pendingReads <- leftover + } + + log.Debug("READING INJECTED %d bytes <<<", n) + return n, err +} + +// TODO: so many EOF edge cases here... +func (conn *FakeConnection) Read(p []byte) (int, error) { + switch { + case isClosedChan(conn.localDone): + return 0, io.ErrClosedPipe + //case isClosedChan(conn.data.RemoteDone): + // return 0, io.EOF + case isClosedChan(conn.readDeadline.wait()): + return 0, os.ErrDeadlineExceeded + } + + // TODO: is there really no better way for priority chan reads? + select { + // see if we have any leftover data from the previous read + case incomplete := <-conn.pendingReads: + log.Trace("reading previously incomplete data") + return conn.readAndBuffer(incomplete, p) + default: + // reason for this extra select: + // if we have BOTH server data and closing information - you HAVE TO use up the data first + select { + // if we have any data: do read it + case injectedData := <-conn.data.ServerData: + log.Trace("server data") + return conn.readAndBuffer(injectedData, p) + default: + // we wait for either some data, closing info, an error or timeout + select { + case data := <-conn.data.ServerData: + if len(data) == 0 { + return 0, io.EOF + } + return conn.readAndBuffer(data, p) + case err := <-conn.data.RemoteError: + return 0, err + case <-conn.localDone: + return 0, io.ErrClosedPipe + case <-conn.data.RemoteDone: + return 0, io.EOF + case <-conn.readDeadline.wait(): + return 0, os.ErrDeadlineExceeded + } + } + } +} + +func (conn *FakeConnection) Write(p []byte) (int, error) { + log.Debug("WRITING %d bytes TO 'REMOTE' >>> \n", len(p)) + + switch { + case isClosedChan(conn.localDone): + return 0, io.ErrClosedPipe + //case isClosedChan(conn.data.RemoteDone): + // return 0, io.EOF + case isClosedChan(conn.readDeadline.wait()): + return 0, os.ErrDeadlineExceeded + } + + // TODO: I guess the deadline should take into consideration the recipient actually getting the packet... + err := rust_bridge.RsSendClientData(conn.requestId, p) + if err != nil { + return 0, err + } else { + return len(p), nil + } +} + +func (conn *FakeConnection) Close() error { + log.Debug("closing FakeConnection") + + close(conn.localDone) + ActiveRequests.Remove(conn.requestId) + + // TODO: if we already received information about remote being closed, + // do we have to send a socks5 closing packet? + return rust_bridge.RsFinishMixnetConnection(conn.requestId) +} + +func (conn *FakeConnection) LocalAddr() net.Addr { + log.Warn("TODO: implement LocalAddr FakeConnection") + return nil +} + +func (conn *FakeConnection) RemoteAddr() net.Addr { + log.Warn("TODO: implement RemoteAddr FakeConnection") + return nil +} + +func (conn *FakeConnection) SetDeadline(t time.Time) error { + log.Trace("Setting deadline to %v\n", t) + + if isClosedChan(conn.localDone) || isClosedChan(conn.data.RemoteDone) { + return io.ErrClosedPipe + } + + conn.readDeadline.set(t) + conn.writeDeadline.set(t) + + return nil +} + +func (conn *FakeConnection) SetReadDeadline(t time.Time) error { + log.Trace("Setting read deadline to %v\n", t) + + if isClosedChan(conn.localDone) || isClosedChan(conn.data.RemoteDone) { + return io.ErrClosedPipe + } + + conn.readDeadline.set(t) + + return nil +} + +func (conn *FakeConnection) SetWriteDeadline(t time.Time) error { + log.Trace("Setting write deadline to %v\n", t) + + if isClosedChan(conn.localDone) || isClosedChan(conn.data.RemoteDone) { + return io.ErrClosedPipe + } + + conn.writeDeadline.set(t) + + return nil +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/state/state.go b/wasm/mix-fetch/go-mix-conn/internal/state/state.go new file mode 100644 index 0000000000..a9b99b9630 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/state/state.go @@ -0,0 +1,124 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package state + +import ( + "go-mix-conn/internal/log" + "go-mix-conn/internal/types" + "sync" + "time" +) + +// ALL THE GLOBALS SHOULD GO HERE +var ActiveRequests *CurrentActiveRequests +var RequestTimeout time.Duration = time.Second * 5 + +// 4.4.7 +var MaxRedirections int = 20 + +func InitialiseGlobalState() { + ActiveRequests = &CurrentActiveRequests{ + Mutex: sync.Mutex{}, + Requests: make(map[types.RequestId]*ActiveRequest), + AddressMapping: make(map[string]types.RequestId), + } +} + +type CurrentActiveRequests struct { + sync.Mutex + Requests map[types.RequestId]*ActiveRequest + AddressMapping map[string]types.RequestId +} + +func (ar *CurrentActiveRequests) GetId(canonicalAddr string) types.RequestId { + log.Trace("getting id associated with request for %s", canonicalAddr) + ar.Lock() + defer ar.Unlock() + return ar.AddressMapping[canonicalAddr] +} + +func (ar *CurrentActiveRequests) Exists(id types.RequestId) bool { + log.Trace("checking if request %d exists", id) + ar.Lock() + defer ar.Unlock() + _, exists := ar.Requests[id] + return exists +} + +func (ar *CurrentActiveRequests) ExistsCanonical(canonicalAddr string) bool { + return ar.GetId(canonicalAddr) != 0 +} + +func (ar *CurrentActiveRequests) Insert(id types.RequestId, canonicalAddr string, inj ConnectionInjector) { + log.Trace("inserting request %d for %s", id, canonicalAddr) + ar.Lock() + defer ar.Unlock() + _, exists := ar.Requests[id] + if exists { + panic("attempted to overwrite active connection id") + } + _, exists = ar.AddressMapping[canonicalAddr] + if exists { + panic("attempted to overwrite active connection canonicalAddr") + } + + ar.Requests[id] = &ActiveRequest{injector: inj, canonicalAddr: canonicalAddr} + ar.AddressMapping[canonicalAddr] = id +} + +func (ar *CurrentActiveRequests) Remove(id types.RequestId) { + log.Trace("removing request %d", id) + ar.Lock() + defer ar.Unlock() + req, exists := ar.Requests[id] + if !exists { + panic("attempted to remove active connection id that doesn't exist") + } + _, exists = ar.AddressMapping[req.canonicalAddr] + if !exists { + panic("attempted to remove active connection canonicalAddr that doesn't exist") + } + + delete(ar.Requests, id) + delete(ar.AddressMapping, req.canonicalAddr) +} + +func (ar *CurrentActiveRequests) InjectData(id types.RequestId, data []byte) { + log.Trace("injecting data for %d", id) + ar.Lock() + defer ar.Unlock() + _, exists := ar.Requests[id] + if !exists { + panic("attempted to write to connection that doesn't exist") + } + ar.Requests[id].injector.ServerData <- data +} + +func (ar *CurrentActiveRequests) CloseRemoteSocket(id types.RequestId) { + log.Trace("closing remote socket for %d", id) + ar.Lock() + defer ar.Unlock() + _, exists := ar.Requests[id] + if !exists { + log.Warn("attempted to close remote socket of a connection that doesn't exist") + return + } + close(ar.Requests[id].injector.RemoteDone) +} + +func (ar *CurrentActiveRequests) SendError(id types.RequestId, err error) { + log.Trace("injecting error for %d: %s", id, err) + ar.Lock() + defer ar.Unlock() + _, exists := ar.Requests[id] + if !exists { + panic("attempted to inject error data to connection that doesn't exist") + } + ar.Requests[id].injector.RemoteError <- err +} + +type ActiveRequest struct { + injector ConnectionInjector + canonicalAddr string +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/types/options.go b/wasm/mix-fetch/go-mix-conn/internal/types/options.go new file mode 100644 index 0000000000..6383aa5c5e --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/types/options.go @@ -0,0 +1,37 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package types + +import ( + "fmt" + "go-mix-conn/internal/jstypes" +) + +type RequestOptions struct { + Redirect jstypes.Redirect + Mode jstypes.Mode + CredentialsMode jstypes.CredentialsMode + ReferrerPolicy jstypes.ReferrerPolicy + Referrer jstypes.Referrer + ResponseTainting jstypes.ResponseTainting + Method string +} + +func (opts RequestOptions) String() string { + return fmt.Sprintf( + "{ Redirect: %s, Mode: %s, credentials: %s, ReferrerPolicy: %s, Referrer: %s, ResponseTainting: %s, Method: %s }", + opts.Redirect, + opts.Mode, + opts.CredentialsMode, + opts.ReferrerPolicy, + opts.Referrer, + opts.ResponseTainting, + opts.Method, + ) +} + +type RequestContext struct { + WasRedirected bool + OverwrittenResponseType jstypes.ResponseType +} diff --git a/wasm/mix-fetch/go-mix-conn/internal/types/types.go b/wasm/mix-fetch/go-mix-conn/internal/types/types.go new file mode 100644 index 0000000000..5c366af950 --- /dev/null +++ b/wasm/mix-fetch/go-mix-conn/internal/types/types.go @@ -0,0 +1,6 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +package types + +type RequestId = uint64 diff --git a/wasm/mix-fetch/internal-dev-node/.gitignore b/wasm/mix-fetch/internal-dev-node/.gitignore new file mode 100644 index 0000000000..6a91a439ea --- /dev/null +++ b/wasm/mix-fetch/internal-dev-node/.gitignore @@ -0,0 +1 @@ +*.sqlite \ No newline at end of file diff --git a/wasm/mix-fetch/internal-dev-node/package-lock.json b/wasm/mix-fetch/internal-dev-node/package-lock.json new file mode 100644 index 0000000000..51943d47e5 --- /dev/null +++ b/wasm/mix-fetch/internal-dev-node/package-lock.json @@ -0,0 +1,1567 @@ +{ + "name": "internal-dev-node", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "internal-dev-node", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@nymproject/mix-fetch-wasm": "file:../../../dist/node/wasm/mix-fetch", + "indexeddbshim": "^13.0.0-pre.1", + "node-fetch": "^3.3.2", + "ws": "^8.13.0" + } + }, + "../../../dist/node/wasm/mix-fetch": { + "name": "@nymproject/mix-fetch-wasm", + "version": "1.2.0-rc.2", + "license": "Apache-2.0" + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", + "optional": true + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "license": "BSD-3-Clause", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nymproject/mix-fetch-wasm": { + "resolved": "../../../dist/node/wasm/mix-fetch", + "link": true + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC" + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "license": "MIT", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "license": "ISC" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/argsarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/argsarray/-/argsarray-0.0.1.tgz", + "integrity": "sha512-u96dg2GcAKtpTrBdDoFIM7PjcBA+6rSP0OR94MOReNRyUECL6MtQt5XXmRr4qrftYaef9+l5hcpO5te7sML1Cg==", + "license": "WTFPL" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-arraybuffer-es6": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64-arraybuffer-es6/-/base64-arraybuffer-es6-3.0.1.tgz", + "integrity": "sha512-bOxevePlYA8Kba1xVnrQSoktrt12UkP6Jhl2wO+GCGbKAkF4fpDxyg7xRFffZYC0kP2RgMPOSRbzmdHReWnMyg==", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/canvas": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", + "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "license": "MIT", + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", + "optional": true + }, + "node_modules/eventtargeter": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/eventtargeter/-/eventtargeter-0.9.0.tgz", + "integrity": "sha512-40f2UpTpS7v2GnXWsMpEUkKoMOlgTDrijhCx4Hq7zvsBhLihA7dn0Ayicb4FO/MOIzD5mLHsLK7/NYqx39LqaA==", + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "license": "ISC", + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC", + "optional": true + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC" + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/humanize-ms/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "optional": true + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immediate": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", + "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", + "license": "MIT" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/indexeddbshim": { + "version": "13.0.0-pre.1", + "resolved": "https://registry.npmjs.org/indexeddbshim/-/indexeddbshim-13.0.0-pre.1.tgz", + "integrity": "sha512-Tl0FAiQvp0zdTiWZf267d6MN0cFk64z8oa39zpexIkX3Nk/AY5iYhPqvpQcGOxXJWdY/IWOyZFZb4K2qhRtxng==", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "canvas": "^2.11.2", + "eventtargeter": "0.9.0", + "sync-promise-expanded": "^1.0.0", + "typeson": "9.0.2", + "typeson-registry": "7.2.1", + "websql-configurable": "^3.0.3" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "license": "MIT", + "optional": true + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", + "optional": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC", + "optional": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" + }, + "node_modules/nan": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "license": "MIT", + "optional": true + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/noop-fn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/noop-fn/-/noop-fn-1.0.0.tgz", + "integrity": "sha512-pQ8vODlgXt2e7A3mIbFDlizkr46r75V+BJxVAyat8Jl7YmI513gG5cfyRL0FedKraoZ+VAouI1h4/IWpus5pcQ==", + "license": "MIT" + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT", + "optional": true + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "license": "MIT", + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sqlite3": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.6.tgz", + "integrity": "sha512-olYkWoKFVNSSSQNvxVUfjiVbz3YtBwTJj+mfV5zpHmqW3sELx2Cf4QCdirMelhM5Zh+KDVaKgQHqCxrqiWHybw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^4.2.0", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sync-promise-expanded": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sync-promise-expanded/-/sync-promise-expanded-1.0.0.tgz", + "integrity": "sha512-pdxxEOaeKO6LghTz0Fe7yw82fx95gtS0SxVgRvIwvN4h9qTie8oOF/pWuH8PGp+PVduS84RXXxO/xrW93Nno9w==", + "license": "ISC", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tiny-queue": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tiny-queue/-/tiny-queue-0.2.1.tgz", + "integrity": "sha512-EijGsv7kzd9I9g0ByCl6h42BWNGUZrlCSejfrb3AKeHC33SGbASu1VDf5O3rRiiUOhAC9CHdZxFPbZu0HmR70A==", + "license": "Apache 2" + }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/typeson": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/typeson/-/typeson-9.0.2.tgz", + "integrity": "sha512-83w1JVRVt22Kj2bIBo4DyhWYh4RKzbuBW5g89ETlPJOv0+LLX4/hANstDr76srTzULePKSl7DqDAtqHADJOwvQ==", + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/typeson-registry": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/typeson-registry/-/typeson-registry-7.2.1.tgz", + "integrity": "sha512-6KBjzf4kK045pPPA6UqC1O3JKhFM4+O9YZf4AtcBX7v/8m8AG1bB3UIJN05PRY9U3E7P7/4Gc4MjPrqwvGq2wQ==", + "license": "MIT", + "dependencies": { + "base64-arraybuffer-es6": "^3.0.0", + "typeson": "^9.0.2", + "whatwg-url": "^12.0.1" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + } + }, + "node_modules/typeson-registry/node_modules/typeson": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/typeson/-/typeson-9.0.3.tgz", + "integrity": "sha512-vsOn+VPbIYI3jgj96vwIhAO0BNmlBxEgBKVmuzl1dwXzQe+3XjRi/gK2zYgAansWYlrtvluy4lvWcL8LF01P3Q==", + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/websql-configurable": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/websql-configurable/-/websql-configurable-3.0.3.tgz", + "integrity": "sha512-Fs+3A2BjI3ukkGtvsZcPS4nGoFE0aqors8YKWgICoOt7dcfdeaTdgoMOoFqlEPHc9u/TS9BEFhKP/A9GttB0CQ==", + "license": "Apache-2.0", + "dependencies": { + "argsarray": "^0.0.1", + "immediate": "^3.2.2", + "noop-fn": "^1.0.0", + "tiny-queue": "^0.2.1" + }, + "optionalDependencies": { + "sqlite3": "^5.0.2" + } + }, + "node_modules/whatwg-url": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz", + "integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==", + "license": "MIT", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + } + } +} diff --git a/wasm/mix-fetch/internal-dev-node/package.json b/wasm/mix-fetch/internal-dev-node/package.json new file mode 100644 index 0000000000..8b2e67d11a --- /dev/null +++ b/wasm/mix-fetch/internal-dev-node/package.json @@ -0,0 +1,17 @@ +{ + "name": "internal-dev-node", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "node src/index.mjs" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@nymproject/mix-fetch-wasm": "file:../../../dist/node/wasm/mix-fetch", + "indexeddbshim": "^13.0.0-pre.1", + "node-fetch": "^3.3.2", + "ws": "^8.13.0" + } +} diff --git a/wasm/mix-fetch/internal-dev-node/src/index.mjs b/wasm/mix-fetch/internal-dev-node/src/index.mjs new file mode 100644 index 0000000000..978645136d --- /dev/null +++ b/wasm/mix-fetch/internal-dev-node/src/index.mjs @@ -0,0 +1,98 @@ +import {Worker} from 'worker_threads'; + +function sleep(ms) { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +} + +class NodeWorkerClient { + worker = null; + clientInitialised = false; + selfAddress = null + + constructor() { + this.worker = new Worker('./src/worker.mjs'); + + this.worker.on("message", message => { + this.handleMessage(message) + }); + + this.worker.on("error", error => { + console.log(error); + }); + + this.worker.on("exit", exitCode => { + console.log(`It exited with code ${exitCode}`); + }) + + } + + initMixFetch = () => { + this.worker.postMessage({kind: 'initRequest', data: {}}) + } + + fetch = (resource, options) => { + this.worker.postMessage({kind: 'fetchRequest', data: {resource, options}}) + } + + handleResponse = (message, senderTag) => { + // console.log(`received raw message: ${message}`) + // console.log(`with senderTag: ${senderTag}`) + // + // let decoded = new TextDecoder().decode(message); + // console.log(`decoded message: "${decoded}"`) + } + + handleMessage = (message) => { + console.log(`handling "${message.kind}"`) + switch (message.kind) { + case 'initResponse': + this.clientInitialised = message.data.done; + break; + case 'receivedResponse': + this.handleResponse(message.data.response) + break; + default: + console.log("UNKOWN MESSAGE") + break; + } + } + + // hehe, that's so disgusting, but I don't want to spend ages in the JS callback hell + // because that's not the point of this example + waitForMixFetch = async () => { + let start = new Date(); + let pollingRate = 100; + let maxWaitSecs = 5; + while (!this.clientInitialised) { + let now = new Date(); + let diff = (now.getTime() - start.getTime()) / 1000; + if (diff > maxWaitSecs) { + return Promise.reject(new Error('failed to initialise mix fetch')) + } + await sleep(pollingRate) + } + } +} + + +async function main() { + let client = new NodeWorkerClient() + client.initMixFetch() + await client.waitForMixFetch() + + await client.fetch("https://nymtech.net", { mode: "unsafe-ignore-cors" }) +} + +await main() + +process.on('SIGTERM', signal => { + console.log(`Process ${process.pid} received a SIGTERM signal`) + process.exit(0) +}) + +process.on('SIGINT', signal => { + console.log(`Process ${process.pid} has been interrupted`) + process.exit(0) +}) \ No newline at end of file diff --git a/wasm/mix-fetch/internal-dev-node/src/polyfill.mjs b/wasm/mix-fetch/internal-dev-node/src/polyfill.mjs new file mode 100644 index 0000000000..4c62b8e7e6 --- /dev/null +++ b/wasm/mix-fetch/internal-dev-node/src/polyfill.mjs @@ -0,0 +1,59 @@ +import crypto from 'node:crypto'; +import fs from 'node:fs'; +import { TextDecoder, TextEncoder } from 'node:util'; +import setGlobalVars from 'indexeddbshim'; +import WebSocket from 'ws'; +import fetch, { + Headers, + Request, + Response, +} from 'node-fetch' + + +if (!globalThis.fs) { + globalThis.fs = fs +} + +if (!globalThis.process) { + globalThis.process = process +} + +if (!globalThis.crypto) { + globalThis.crypto = { + getRandomValues(b) { + crypto.randomFillSync(b); + }, + } +} + +if (!globalThis.performance) { + globalThis.performance = { + now() { + const [sec, nsec] = process.hrtime(); + return sec * 1000 + nsec / 1000000; + }, + }; +} + +if (!globalThis.TextEncoder) { + globalThis.TextEncoder = TextEncoder +} + +if (!globalThis.TextDecoder) { + globalThis.TextDecoder = TextDecoder +} + +if (!globalThis.fetch) { + globalThis.fetch = fetch + globalThis.Headers = Headers + globalThis.Request = Request + globalThis.Response = Response +} + +// checkOrigin:false is required to avoid SecurityError Cannot open +// an IndexedDB database from an opaque origin. +setGlobalVars(globalThis, {checkOrigin: false}) +globalThis.WebSocket = WebSocket + +// has to be loaded after all the polyfill action +import('@nymproject/mix-fetch-wasm/wasm_exec.js') diff --git a/wasm/mix-fetch/internal-dev-node/src/worker.mjs b/wasm/mix-fetch/internal-dev-node/src/worker.mjs new file mode 100644 index 0000000000..95751fec17 --- /dev/null +++ b/wasm/mix-fetch/internal-dev-node/src/worker.mjs @@ -0,0 +1,117 @@ +import {parentPort} from 'worker_threads'; +import {setupMixFetch, set_panic_hook, send_client_data, start_new_mixnet_connection, mix_fetch_initialised, finish_mixnet_connection} from '@nymproject/mix-fetch-wasm'; +import fs from 'node:fs'; +import("./polyfill.mjs") + +// Sorry Mark, but I don't want to deal with bundling hell to get this one work via proper import : ( +let goWasmPath = "../../../dist/node/wasm/mix-fetch/go_conn.wasm" +// import goWasm from '@nymproject/mix-fetch-wasm/go_conn.wasm' + + +function sleep(ms) { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +} + +function setupRsGoBridge() { + // (note: reason for intermediate `__rs_go_bridge__` object is to decrease global scope bloat + // and to discourage users from trying to call those methods directly) + globalThis.__rs_go_bridge__ = {} + globalThis.__rs_go_bridge__.send_client_data = send_client_data + globalThis.__rs_go_bridge__.start_new_mixnet_connection = start_new_mixnet_connection + globalThis.__rs_go_bridge__.mix_fetch_initialised = mix_fetch_initialised + globalThis.__rs_go_bridge__.finish_mixnet_connection = finish_mixnet_connection +} + +async function loadGoWasm() { + // I... don't even want to know. Javascript (and node) works in mysterious ways... + if (!globalThis.Go) { + await sleep(500) + } + + console.log(globalThis.Origin) + + const go = new Go() + const blob = fs.readFileSync(goWasmPath); + const wasmObj = await WebAssembly.instantiate(blob, go.importObject) + const goWasm = wasmObj.instance + go.run(goWasm) +} + +async function logFetchResult(res) { + let text = await res.text() + console.log("HEADERS: ", ...res.headers) + console.log("STATUS: ", res.status) + console.log("STATUS TEXT: ", res.statusText) + console.log("OK: ", res.ok) + console.log("TYPE: ", res.type) + console.log("URL: ", res.url) + console.log("BODYUSED: ", res.bodyUsed) + console.log("REDIRECTED: ", res.redirected) + console.log("TEXT: ", text) +} + + +let initDone = false + +parentPort.on('message', async message => { + await handleMessage(message) +}); + +async function handleMessage(message) { + console.log(`handling "${message.kind}"`) + switch (message.kind) { + case 'initRequest': + await initialiseMixFetch() + break; + case 'fetchRequest': + await handleFetchRequest(message.data.resource, message.data.options); + break; + default: + console.log("UNKOWN MESSAGE") + break; + } +} + +async function handleFetchRequest(resource, options) { + console.log("will fetch", resource, options) + let res = await mixFetch(resource, options) + await logFetchResult(res) +} + +async function nativeSetup(onMessageHandler) { + const noCoverTrafficOverride = { + traffic: { disableMainPoissonPacketDistribution: true }, + coverTraffic: { disableLoopCoverTrafficStream: true }, + } + const mixFetchOverride = { + requestTimeoutMs: 10000 + } + + await setupMixFetch({ storagePassphrase: "foomp", clientId: "my-client", clientOverride: noCoverTrafficOverride, mixFetchOverride }) + +} + +function finishInit() { + initDone = true + parentPort.postMessage({kind: 'initResponse', data: {done: initDone}}) +} + +async function initialiseMixFetch() { + if (initDone) { + return finishInit() + } + + setupRsGoBridge() + await loadGoWasm() + + // sets up better stack traces in case of in-rust panics + set_panic_hook(); + + console.log('Instantiating mix fetch...'); + await nativeSetup() + console.log('mix fetch client running!'); + + finishInit() +} diff --git a/wasm/mix-fetch/internal-dev-node/yarn.lock b/wasm/mix-fetch/internal-dev-node/yarn.lock new file mode 100644 index 0000000000..a89db430e7 --- /dev/null +++ b/wasm/mix-fetch/internal-dev-node/yarn.lock @@ -0,0 +1,938 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@gar/promisify@^1.0.1": + version "1.1.3" + resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz" + integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== + +"@mapbox/node-pre-gyp@^1.0.0": + version "1.0.11" + resolved "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz" + integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ== + dependencies: + detect-libc "^2.0.0" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.7" + nopt "^5.0.0" + npmlog "^5.0.1" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.11" + +"@npmcli/fs@^1.0.0": + version "1.1.1" + resolved "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz" + integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== + dependencies: + "@gar/promisify" "^1.0.1" + semver "^7.3.5" + +"@npmcli/move-file@^1.0.1": + version "1.1.2" + resolved "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz" + integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== + dependencies: + mkdirp "^1.0.4" + rimraf "^3.0.2" + +"@nymproject/mix-fetch-wasm@file:../../../dist/node/wasm/mix-fetch": + version "1.2.0-rc.2" + +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + +abbrev@1: + version "1.1.1" + resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +agent-base@6, agent-base@^6.0.2: + version "6.0.2" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +agentkeepalive@^4.1.3: + version "4.5.0" + resolved "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz" + integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== + dependencies: + humanize-ms "^1.2.1" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +are-we-there-yet@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz" + integrity sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +argsarray@^0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/argsarray/-/argsarray-0.0.1.tgz" + integrity sha512-u96dg2GcAKtpTrBdDoFIM7PjcBA+6rSP0OR94MOReNRyUECL6MtQt5XXmRr4qrftYaef9+l5hcpO5te7sML1Cg== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-arraybuffer-es6@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/base64-arraybuffer-es6/-/base64-arraybuffer-es6-3.0.1.tgz" + integrity sha512-bOxevePlYA8Kba1xVnrQSoktrt12UkP6Jhl2wO+GCGbKAkF4fpDxyg7xRFffZYC0kP2RgMPOSRbzmdHReWnMyg== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +cacache@^15.2.0: + version "15.3.0" + resolved "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz" + integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== + dependencies: + "@npmcli/fs" "^1.0.0" + "@npmcli/move-file" "^1.0.1" + chownr "^2.0.0" + fs-minipass "^2.0.0" + glob "^7.1.4" + infer-owner "^1.0.4" + lru-cache "^6.0.0" + minipass "^3.1.1" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^1.0.3" + p-map "^4.0.0" + promise-inflight "^1.0.1" + rimraf "^3.0.2" + ssri "^8.0.1" + tar "^6.0.2" + unique-filename "^1.1.1" + +canvas@^2.11.2: + version "2.11.2" + resolved "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz" + integrity sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.0" + nan "^2.17.0" + simple-get "^3.0.3" + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +color-support@^1.1.2, color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +console-control-strings@^1.0.0, console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + +debug@4, debug@^4.3.3: + version "4.3.4" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +detect-libc@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz" + integrity sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encoding@^0.1.12: + version "0.1.13" + resolved "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +err-code@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz" + integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== + +eventtargeter@0.9.0: + version "0.9.0" + resolved "https://registry.npmjs.org/eventtargeter/-/eventtargeter-0.9.0.tgz" + integrity sha512-40f2UpTpS7v2GnXWsMpEUkKoMOlgTDrijhCx4Hq7zvsBhLihA7dn0Ayicb4FO/MOIzD5mLHsLK7/NYqx39LqaA== + +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + +gauge@^4.0.3: + version "4.0.4" + resolved "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz" + integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.3" + console-control-strings "^1.1.0" + has-unicode "^2.0.1" + signal-exit "^3.0.7" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.5" + +glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" + 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" + +graceful-fs@^4.2.6: + version "4.2.11" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + +http-cache-semantics@^4.1.0: + version "4.1.1" + resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz" + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== + dependencies: + ms "^2.0.0" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +immediate@^3.2.2: + version "3.3.0" + resolved "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +indexeddbshim@^13.0.0-pre.1: + version "13.0.0-pre.1" + resolved "https://registry.npmjs.org/indexeddbshim/-/indexeddbshim-13.0.0-pre.1.tgz" + integrity sha512-Tl0FAiQvp0zdTiWZf267d6MN0cFk64z8oa39zpexIkX3Nk/AY5iYhPqvpQcGOxXJWdY/IWOyZFZb4K2qhRtxng== + dependencies: + canvas "^2.11.2" + eventtargeter "0.9.0" + sync-promise-expanded "^1.0.0" + typeson "9.0.2" + typeson-registry "7.2.1" + websql-configurable "^3.0.3" + +infer-owner@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ip@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz" + integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-lambda@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz" + integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-fetch-happen@^9.1.0: + version "9.1.0" + resolved "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz" + integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== + dependencies: + agentkeepalive "^4.1.3" + cacache "^15.2.0" + http-cache-semantics "^4.1.0" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-lambda "^1.0.1" + lru-cache "^6.0.0" + minipass "^3.1.3" + minipass-collect "^1.0.2" + minipass-fetch "^1.3.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.2" + promise-retry "^2.0.1" + socks-proxy-agent "^6.0.0" + ssri "^8.0.0" + +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + +minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minipass-collect@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz" + integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== + dependencies: + minipass "^3.0.0" + +minipass-fetch@^1.3.2: + version "1.4.1" + resolved "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz" + integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw== + dependencies: + minipass "^3.1.0" + minipass-sized "^1.0.3" + minizlib "^2.0.0" + optionalDependencies: + encoding "^0.1.12" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== + dependencies: + minipass "^3.0.0" + +minipass-sized@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz" + integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== + dependencies: + minipass "^3.0.0" + +minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: + version "3.3.6" + resolved "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +minizlib@^2.0.0, minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^1.0.3, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.0.0: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nan@^2.17.0: + version "2.17.0" + resolved "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz" + integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== + +negotiator@^0.6.2: + version "0.6.3" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +node-addon-api@^4.2.0: + version "4.3.0" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz" + integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== + +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + +node-fetch@^2.6.7: + version "2.6.12" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz" + integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^3.3.2: + version "3.3.2" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz" + 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-gyp@8.x: + version "8.4.1" + resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz" + integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== + dependencies: + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.6" + make-fetch-happen "^9.1.0" + nopt "^5.0.0" + npmlog "^6.0.0" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.2" + which "^2.0.2" + +noop-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/noop-fn/-/noop-fn-1.0.0.tgz" + integrity sha512-pQ8vODlgXt2e7A3mIbFDlizkr46r75V+BJxVAyat8Jl7YmI513gG5cfyRL0FedKraoZ+VAouI1h4/IWpus5pcQ== + +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== + dependencies: + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + +npmlog@^6.0.0: + version "6.0.2" + resolved "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz" + integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== + dependencies: + are-we-there-yet "^3.0.0" + console-control-strings "^1.1.0" + gauge "^4.0.3" + set-blocking "^2.0.0" + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +once@^1.3.0, once@^1.3.1: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz" + integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== + +promise-retry@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz" + integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== + dependencies: + err-code "^2.0.2" + retry "^0.12.0" + +punycode@^2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^6.0.0: + version "6.3.1" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.5: + version "7.5.4" + resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +signal-exit@^3.0.0, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^3.0.3: + version "3.1.1" + resolved "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz" + integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + +socks-proxy-agent@^6.0.0: + version "6.2.1" + resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz" + integrity sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ== + dependencies: + agent-base "^6.0.2" + debug "^4.3.3" + socks "^2.6.2" + +socks@^2.6.2: + version "2.7.1" + resolved "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz" + integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== + dependencies: + ip "^2.0.0" + smart-buffer "^4.2.0" + +sqlite3@^5.0.2: + version "5.1.6" + resolved "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.6.tgz" + integrity sha512-olYkWoKFVNSSSQNvxVUfjiVbz3YtBwTJj+mfV5zpHmqW3sELx2Cf4QCdirMelhM5Zh+KDVaKgQHqCxrqiWHybw== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.0" + node-addon-api "^4.2.0" + tar "^6.1.11" + optionalDependencies: + node-gyp "8.x" + +ssri@^8.0.0, ssri@^8.0.1: + version "8.0.1" + resolved "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz" + integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== + dependencies: + minipass "^3.1.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + 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" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +sync-promise-expanded@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/sync-promise-expanded/-/sync-promise-expanded-1.0.0.tgz" + integrity sha512-pdxxEOaeKO6LghTz0Fe7yw82fx95gtS0SxVgRvIwvN4h9qTie8oOF/pWuH8PGp+PVduS84RXXxO/xrW93Nno9w== + +tar@^6.0.2, tar@^6.1.11, tar@^6.1.2: + version "6.1.15" + resolved "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz" + integrity sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +tiny-queue@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/tiny-queue/-/tiny-queue-0.2.1.tgz" + integrity sha512-EijGsv7kzd9I9g0ByCl6h42BWNGUZrlCSejfrb3AKeHC33SGbASu1VDf5O3rRiiUOhAC9CHdZxFPbZu0HmR70A== + +tr46@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz" + integrity sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw== + dependencies: + punycode "^2.3.0" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +typeson-registry@7.2.1: + version "7.2.1" + resolved "https://registry.npmjs.org/typeson-registry/-/typeson-registry-7.2.1.tgz" + integrity sha512-6KBjzf4kK045pPPA6UqC1O3JKhFM4+O9YZf4AtcBX7v/8m8AG1bB3UIJN05PRY9U3E7P7/4Gc4MjPrqwvGq2wQ== + dependencies: + base64-arraybuffer-es6 "^3.0.0" + typeson "^9.0.2" + whatwg-url "^12.0.1" + +typeson@9.0.2: + version "9.0.2" + resolved "https://registry.npmjs.org/typeson/-/typeson-9.0.2.tgz" + integrity sha512-83w1JVRVt22Kj2bIBo4DyhWYh4RKzbuBW5g89ETlPJOv0+LLX4/hANstDr76srTzULePKSl7DqDAtqHADJOwvQ== + +typeson@^9.0.2: + version "9.0.3" + resolved "https://registry.npmjs.org/typeson/-/typeson-9.0.3.tgz" + integrity sha512-vsOn+VPbIYI3jgj96vwIhAO0BNmlBxEgBKVmuzl1dwXzQe+3XjRi/gK2zYgAansWYlrtvluy4lvWcL8LF01P3Q== + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== + dependencies: + imurmurhash "^0.1.4" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +web-streams-polyfill@^3.0.3: + version "3.2.1" + resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz" + integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + +websql-configurable@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/websql-configurable/-/websql-configurable-3.0.3.tgz" + integrity sha512-Fs+3A2BjI3ukkGtvsZcPS4nGoFE0aqors8YKWgICoOt7dcfdeaTdgoMOoFqlEPHc9u/TS9BEFhKP/A9GttB0CQ== + dependencies: + argsarray "^0.0.1" + immediate "^3.2.2" + noop-fn "^1.0.0" + tiny-queue "^0.2.1" + optionalDependencies: + sqlite3 "^5.0.2" + +whatwg-url@^12.0.1: + version "12.0.1" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz" + integrity sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ== + dependencies: + tr46 "^4.1.1" + webidl-conversions "^7.0.0" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.2, wide-align@^1.1.5: + version "1.1.5" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@^8.13.0: + version "8.13.0" + resolved "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/wasm/mix-fetch/internal-dev/.gitignore b/wasm/mix-fetch/internal-dev/.gitignore new file mode 100644 index 0000000000..f06235c460 --- /dev/null +++ b/wasm/mix-fetch/internal-dev/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist diff --git a/wasm/mix-fetch/internal-dev/bootstrap.js b/wasm/mix-fetch/internal-dev/bootstrap.js new file mode 100644 index 0000000000..a017926b28 --- /dev/null +++ b/wasm/mix-fetch/internal-dev/bootstrap.js @@ -0,0 +1,5 @@ +// A dependency graph that contains any wasm must all be imported +// asynchronously. This `bootstrap.js` file does the single async import, so +// that no one else needs to worry about it again. +import('./index.js') + .catch(e => console.error('Error importing `index.js`:', e)); diff --git a/wasm/mix-fetch/internal-dev/index.html b/wasm/mix-fetch/internal-dev/index.html new file mode 100644 index 0000000000..ffe5047581 --- /dev/null +++ b/wasm/mix-fetch/internal-dev/index.html @@ -0,0 +1,27 @@ + + + + + + + Nym MixFetch Demo + + + + +

Mix Fetch Demo

+
+ + + +
+ + +
+

+ +

+ + + + \ No newline at end of file diff --git a/wasm/mix-fetch/internal-dev/index.js b/wasm/mix-fetch/internal-dev/index.js new file mode 100644 index 0000000000..20c4a6894d --- /dev/null +++ b/wasm/mix-fetch/internal-dev/index.js @@ -0,0 +1,96 @@ +// Copyright 2020-2023 Nym Technologies SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +class WebWorkerClient { + worker = null; + + constructor() { + this.worker = new Worker('./worker.js'); + + this.worker.onmessage = (ev) => { + if (ev.data && ev.data.kind) { + switch (ev.data.kind) { + case 'DisplayString': + const { rawString } = ev.data.args; + displayReceivedRawString(rawString) + break; + } + } + }; + } + + doFetch = (target) => { + if (!this.worker) { + console.error('Could not send message because worker does not exist'); + return; + } + + this.worker.postMessage({ + kind: 'FetchPayload', + args: { + target, + }, + }); + } +} + +let client = null; + +async function main() { + client = new WebWorkerClient(); + + const fetchButton = document.querySelector('#fetch-button'); + fetchButton.onclick = function () { + doFetch(); + } +} + + +async function doFetch() { + const payload = document.getElementById('fetch_payload').value; + await client.doFetch(payload) + + displaySend(`clicked the button and the payload is: ${payload}...`); +} + +/** + * Display messages that have been sent up the websocket. Colours them blue. + * + * @param {string} message + */ +function displaySend(message) { + let timestamp = new Date().toISOString().substr(11, 12); + + let sendDiv = document.createElement('div'); + let paragraph = document.createElement('p'); + paragraph.setAttribute('style', 'color: blue'); + let paragraphContent = document.createTextNode(timestamp + ' sent >>> ' + message); + paragraph.appendChild(paragraphContent); + + sendDiv.appendChild(paragraph); + document.getElementById('output').appendChild(sendDiv); +} + +function displayReceivedRawString(raw) { + let timestamp = new Date().toISOString().substr(11, 12); + let receivedDiv = document.createElement('div'); + let paragraph = document.createElement('p'); + paragraph.setAttribute('style', 'color: green'); + let paragraphContent = document.createTextNode(timestamp + ' received >>> ' + raw); + paragraph.appendChild(paragraphContent); + receivedDiv.appendChild(paragraph); + document.getElementById('output').appendChild(receivedDiv); +} + +main(); diff --git a/wasm/mix-fetch/internal-dev/package.json b/wasm/mix-fetch/internal-dev/package.json new file mode 100644 index 0000000000..105582d79b --- /dev/null +++ b/wasm/mix-fetch/internal-dev/package.json @@ -0,0 +1,41 @@ +{ + "name": "create-wasm-app", + "version": "0.1.0", + "description": "create an app to fetch data through the mixnet", + "main": "index.js", + "bin": { + "create-wasm-app": ".bin/create-wasm-app.js" + }, + "scripts": { + "build": "webpack --config webpack.config.js", + "build:wasm": "cd ../ && make wasm-build", + "start": "webpack-dev-server --port 8001" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/rustwasm/create-wasm-app.git" + }, + "keywords": [ + "webassembly", + "wasm", + "rust", + "webpack" + ], + "author": "Dave Hrycyszyn ", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/nymtech/nym/issues" + }, + "homepage": "https://nymtech.net/docs", + "devDependencies": { + "copy-webpack-plugin": "^11.0.0", + "hello-wasm-pack": "^0.1.0", + "webpack": "^5.70.0", + "webpack-cli": "^4.9.2", + "webpack-dev-server": "^4.7.4" + }, + "dependencies": { + "@nymproject/nym-mix-fetch": "file:../pkg", + "go-mix-conn": "file:../go-mix-conn/build" + } +} diff --git a/wasm/mix-fetch/internal-dev/webpack.config.js b/wasm/mix-fetch/internal-dev/webpack.config.js new file mode 100644 index 0000000000..1cf7d49e34 --- /dev/null +++ b/wasm/mix-fetch/internal-dev/webpack.config.js @@ -0,0 +1,37 @@ +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const path = require('path'); + +module.exports = { + performance: { + hints: false, + maxEntrypointSize: 512000, + maxAssetSize: 512000 + }, + entry: { + bootstrap: './bootstrap.js', + worker: './worker.js', + }, + output: { + path: path.resolve(__dirname, 'dist'), + filename: '[name].js', + }, + mode: 'development', + // mode: 'production', + plugins: [ + new CopyWebpackPlugin({ + patterns: [ + 'index.html', + { + from: '../pkg/*.(js|wasm)', + to: '[name][ext]', + }, + { + from: '../go-mix-conn/build/*.(js|wasm)', + to: '[name][ext]', + }, + ], + }), + + ], + experiments: { syncWebAssembly: true }, +}; diff --git a/wasm/mix-fetch/internal-dev/worker.js b/wasm/mix-fetch/internal-dev/worker.js new file mode 100644 index 0000000000..fd56187f68 --- /dev/null +++ b/wasm/mix-fetch/internal-dev/worker.js @@ -0,0 +1,278 @@ +// Copyright 2020-2023 Nym Technologies SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +const RUST_WASM_URL = "nym_mix_fetch_bg.wasm" +const GO_WASM_URL = "main.wasm" + +importScripts('nym_mix_fetch.js'); +importScripts('wasm_exec.js'); + +console.log('Initializing worker'); + +// wasm_bindgen creates a global variable (with the exports attached) that is in scope after `importScripts` +const { + default_debug, + no_cover_debug, + NymClient, + set_panic_hook, + Config, + GatewayEndpointConfig, + ClientStorage, + MixFetchConfig, + send_client_data, + start_new_mixnet_connection, + setupMixFetch, + setupMixFetchWithConfig, + mix_fetch_initialised, + finish_mixnet_connection} = wasm_bindgen; + +let client = null; +let tester = null; +const go = new Go(); // Defined in wasm_exec.js +var goWasm; + +async function logFetchResult(res) { + console.log(res) + let text = await res.text() + console.log("HEADERS: ", ...res.headers) + console.log("STATUS: ", res.status) + console.log("STATUS TEXT: ", res.statusText) + console.log("OK: ", res.ok) + console.log("TYPE: ", res.type) + console.log("URL: ", res.url) + console.log("BODYUSED: ", res.bodyUsed) + console.log("REDIRECTED: ", res.redirected) + console.log("TEXT: ", text) + + self.postMessage({ + kind: 'DisplayString', + args: { + rawString: text, + }, + }); +} + +async function wasm_bindgenSetup() { + const preferredGateway = "6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; + const validator = 'https://qa-nym-api.qa.nymte.ch/api'; + + // local + const mixFetchNetworkRequesterAddress= "2o47bhnXWna6VEyt4mXMGQQAbXfpKmX7BkjkxUz8uQVi.6uQGnCqSczpXwh86NdbsCoDDXuqZQM9Uwko8GE7uC9g8@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; + // const mixFetchNetworkRequesterAddress= "GqiGWmKRCbGQFSqH88BzLKijvZgipnqhmbNFsmkZw84t.4L8sXFuAUyUYyHZYgMdM3AtiusKnYUft6Pd8e41rrCHA@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; + + // STEP 1. construct config + // those are just some examples, there are obviously more permutations; + // note, the extra optional argument is of the following type: + // /* + // export interface MixFetchConfigOpts { + // id?: string; + // nymApi?: string; + // nyxd?: string; + // debug?: DebugWasm; + // } + // */ + // + // const debug = no_cover_debug() + // + // #1 + // const config = new MixFetchConfig(mixFetchNetworkRequesterAddress, { id: 'my-awesome-mix-fetch-client', nymApi: validator, debug: debug} ); + // #2 + // const config = new MixFetchConfig(mixFetchNetworkRequesterAddress, { nymApi: validator, debug: debug} ); + // #3 + // const config = new MixFetchConfig(mixFetchNetworkRequesterAddress, { id: 'my-awesome-mix-fetch-client' } ); + // + // #4 + const differentDebug = default_debug() + const updatedTraffic = differentDebug.traffic; + updatedTraffic.use_extended_packet_size = true + updatedTraffic.average_packet_delay_ms = 666; + differentDebug.traffic = updatedTraffic; + + const config = new MixFetchConfig(mixFetchNetworkRequesterAddress, { debug: differentDebug } ); + // + // // STEP 2. setup the client + // // note, the extra optional argument is of the following type: + // /* + // export interface MixFetchOptsSimple { + // preferredGateway?: string; + // storagePassphrase?: string; + // } + // */ + // #1 + await setupMixFetchWithConfig(config) + // + // #2 + // await setupMixFetchWithConfig(config, { storagePassphrase: "foomp" }) + // + // #3 + // await setupMixFetchWithConfig(config, { storagePassphrase: "foomp", preferredGateway }) +} + +async function nativeSetup() { + const preferredGateway = "6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; + const validator = 'https://qa-nym-api.qa.nymte.ch/api'; + + // local + const mixFetchNetworkRequesterAddress= "2o47bhnXWna6VEyt4mXMGQQAbXfpKmX7BkjkxUz8uQVi.6uQGnCqSczpXwh86NdbsCoDDXuqZQM9Uwko8GE7uC9g8@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; + // const mixFetchNetworkRequesterAddress= "GqiGWmKRCbGQFSqH88BzLKijvZgipnqhmbNFsmkZw84t.4L8sXFuAUyUYyHZYgMdM3AtiusKnYUft6Pd8e41rrCHA@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; + + // those are just some examples, there are obviously more permutations; + // note, the extra optional argument is of the following type: + /* + export interface MixFetchOpts extends MixFetchOptsSimple { + clientId?: string; + nymApiUrl?: string; + nyxdUrl?: string; + clientOverride?: DebugWasmOverride; + mixFetchOverride?: MixFetchDebugOverride; + } + + where + export interface MixFetchDebugOverride { + requestTimeoutMs?: number; + } + + and `DebugWasmOverride` is a rather nested struct that you can look up yourself : ) + */ + + // #1 + // await setupMixFetch(mixFetchNetworkRequesterAddress) + // #2 + // await setupMixFetch(mixFetchNetworkRequesterAddress, { nymApiUrl: validator }) + // // #3 + const noCoverTrafficOverride = { + traffic: { disableMainPoissonPacketDistribution: true }, + coverTraffic: { disableLoopCoverTrafficStream: true }, + } + const mixFetchOverride = { + requestTimeoutMs: 10000 + } + + await setupMixFetch(mixFetchNetworkRequesterAddress, { storagePassphrase: "foomp", nymApiUrl: validator, clientId: "my-client", clientOverride: noCoverTrafficOverride, mixFetchOverride }) +} + +async function testMixFetch() { + console.log('Instantiating Mix Fetch...'); + // await wasm_bindgenSetup() + + await nativeSetup() + + + console.log('Mix Fetch client running!'); + + // Set callback to handle messages passed to the worker. + self.onmessage = async event => { + if (event.data && event.data.kind) { + switch (event.data.kind) { + case 'FetchPayload': { + const {target} = event.data.args; + const url = target; + + const controller = new AbortController(); + const signal = controller.signal; + + const args = { mode: "cors", redirect: "manual", signal } + // const args = { mode: "unsafe-ignore-cors" } + + setTimeout(() => { + console.warn("timeout") + controller.abort() + }, 10000) + + + try { + console.log('using mixFetch...'); + const mixFetchRes = await mixFetch(url, args) + console.log(">>> MIX FETCH") + await logFetchResult(mixFetchRes) + } catch(e) { + console.error("mix fetch request failure: ", e) + } + + // try { + // console.log('using normal Fetch...'); + // const fetchRes = await fetch(url, args) + // console.log(">>> NORMAL FETCH") + // await logFetchResult(fetchRes) + // } catch(e) { + // console.error("fetch request failure: ", e) + // } + } + } + } + }; +} + + +// TODO: look into https://www.aaron-powell.com/posts/2019-02-08-golang-wasm-5-compiling-with-webpack/ +async function loadGoWasm() { + const resp = await fetch(GO_WASM_URL); + + if ('instantiateStreaming' in WebAssembly) { + const wasmObj = await WebAssembly.instantiateStreaming(resp, go.importObject) + goWasm = wasmObj.instance + go.run(goWasm) + } else { + const bytes = await resp.arrayBuffer() + const wasmObj = await WebAssembly.instantiate(bytes, go.importObject) + goWasm = wasmObj.instance + go.run(goWasm) + } +} + +function setupRsGoBridge() { + // (note: reason for intermediate `__rs_go_bridge__` object is to decrease global scope bloat + // and to discourage users from trying to call those methods directly) + self.__rs_go_bridge__ = {} + self.__rs_go_bridge__.send_client_data = send_client_data + self.__rs_go_bridge__.start_new_mixnet_connection = start_new_mixnet_connection + self.__rs_go_bridge__.mix_fetch_initialised = mix_fetch_initialised + self.__rs_go_bridge__.finish_mixnet_connection = finish_mixnet_connection +} + +async function main() { + console.log(">>>>>>>>>>>>>>>>>>>>> JS WORKER MAIN START"); + + // load rust WASM package + await wasm_bindgen(RUST_WASM_URL); + console.log('Loaded RUST WASM'); + + // load go WASM package + await loadGoWasm(); + console.log("Loaded GO WASM"); + + // sets up better stack traces in case of in-rust panics + set_panic_hook(); + + setupRsGoBridge(); + + goWasmSetLogging("trace") + + // test mixFetch + await testMixFetch(); + // + // // run test on simplified and dedicated tester: + // // await testWithTester() + // + // // hook-up the whole client for testing + // // await testWithNymClient() + // + // // 'Normal' client setup (to send 'normal' messages) + // // await normalNymClientUsage() + // + console.log(">>>>>>>>>>>>>>>>>>>>> JS WORKER MAIN END") +} + +// Let's get started! +main(); \ No newline at end of file diff --git a/clients/webassembly/internal-dev/yarn.lock b/wasm/mix-fetch/internal-dev/yarn.lock similarity index 99% rename from clients/webassembly/internal-dev/yarn.lock rename to wasm/mix-fetch/internal-dev/yarn.lock index ee8eafc744..efd9b8367d 100644 --- a/clients/webassembly/internal-dev/yarn.lock +++ b/wasm/mix-fetch/internal-dev/yarn.lock @@ -74,7 +74,7 @@ fastq "^1.6.0" "@nymproject/nym-client-wasm@file:../pkg": - version "1.1.0" + version "1.1.1" "@types/body-parser@*": version "1.19.2" @@ -1028,6 +1028,9 @@ globby@^12.0.2: merge2 "^1.4.1" slash "^4.0.0" +"go-mix-conn@file:../go-mix-conn/build": + version "0.0.0" + graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" diff --git a/wasm/mix-fetch/src/active_requests.rs b/wasm/mix-fetch/src/active_requests.rs new file mode 100644 index 0000000000..a7407aa317 --- /dev/null +++ b/wasm/mix-fetch/src/active_requests.rs @@ -0,0 +1,142 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::error::MixFetchError; +use crate::go_bridge::{goWasmCloseRemoteSocket, goWasmInjectConnError, goWasmInjectServerData}; +use crate::RequestId; +use nym_ordered_buffer::OrderedMessageBuffer; +use nym_socks5_requests::SocketData; +use rand::{thread_rng, RngCore}; +use std::collections::HashMap; +use std::sync::Arc; +use tokio::sync::Mutex; +use wasm_utils::{console_error, console_log}; + +#[derive(Clone, Default)] +pub struct ActiveRequests { + // TODO: think whether we need sync or async mutex here + inner: Arc>>, +} + +impl ActiveRequests { + pub async fn start_new(&self) -> RequestId { + let mut guard = self.inner.lock().await; + let req = ActiveRequest::new(); + let mut rng = thread_rng(); + let request_id = loop { + let candidate = rng.next_u64(); + if !guard.contains_key(&candidate) { + break candidate; + } + }; + + console_log!("starting new request {request_id}"); + + // it's impossible to insert a duplicate entry here since we're holding the lock for the map + // and we've generated an id that must have been unique + guard.insert(request_id, req); + + request_id + } + + pub async fn get_sending_sequence(&self, id: RequestId) -> Option { + let mut guard = self.inner.lock().await; + if let Some(req) = guard.get_mut(&id) { + Some(req.next_sending_seq()) + } else { + console_error!("attempted to get sending sequence of request {id}, however it no longer exists. Has it been aborted?"); + None + } + } + + pub async fn finish(&self, id: RequestId) { + let mut guard = self.inner.lock().await; + let old = guard.remove(&id); + if old.is_none() { + console_error!("attempted to finish request {id}, but it seems to have never existed?") + } + } + + pub async fn reject(&self, id: RequestId, err: MixFetchError) { + let mut guard = self.inner.lock().await; + let old = guard.remove(&id); + if old.is_none() { + console_error!("attempted to reject request {id}, but it seems to have never existed?") + } + + goWasmInjectConnError(id.to_string(), err.to_string()) + } + + pub async fn try_send_data_to_go(&self, data: SocketData) { + let id = data.header.connection_id; + let mut guard = self.inner.lock().await; + let Some(req) = guard.get_mut(&id) else { + // if there's no data and the socket is closed, we're all good because our local must have already closed + if !data.data.is_empty() || !data.header.local_socket_closed { + console_error!("attempted to send data for request {id}, however it no longer exists. Has it been aborted?"); + } + + // TODO: if it doesn't exist here, make sure to clear Go's memory too + return; + }; + + if let Err(err) = req.insert_data(data) { + console_error!("failed to insert request data: {err}"); + // this unwrap cannot possibly fail as we're holding an exclusive lock for the data + // and we have just borrowed the content + guard.remove(&id).unwrap(); + return goWasmCloseRemoteSocket(id.to_string()); + } + + // TODO: clean this one up + if let Some(contiguous_data) = req.received_data.read() { + // TODO: deal with closing socket, etc. + if !contiguous_data.data.is_empty() { + goWasmInjectServerData(id.to_string(), contiguous_data.data); + } + // TODO: that's very crappy way of doing it. + if Some(contiguous_data.last_sequence) == req.finished_at { + goWasmCloseRemoteSocket(id.to_string()); + } + } + } +} + +struct ActiveRequest { + received_data: OrderedMessageBuffer, + finished_at: Option, + + sending_seq: u64, +} + +impl ActiveRequest { + fn new() -> Self { + ActiveRequest { + received_data: Default::default(), + finished_at: None, + sending_seq: 0, + } + } + + fn next_sending_seq(&mut self) -> u64 { + let next = self.sending_seq; + self.sending_seq += 1; + next + } + + fn insert_data(&mut self, data: SocketData) -> Result<(), MixFetchError> { + if data.header.local_socket_closed { + if let Some(already_finished) = self.finished_at { + return Err(MixFetchError::DuplicateSocketClosure { + request: data.header.connection_id, + first: already_finished, + other: data.header.seq, + }); + } + self.finished_at = Some(data.header.seq) + } + + self.received_data.write(data.header.seq, data.data)?; + Ok(()) + } +} diff --git a/wasm/mix-fetch/src/client.rs b/wasm/mix-fetch/src/client.rs new file mode 100644 index 0000000000..27f871feda --- /dev/null +++ b/wasm/mix-fetch/src/client.rs @@ -0,0 +1,258 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::active_requests::ActiveRequests; +use crate::config::MixFetchConfig; +use crate::error::MixFetchError; +use crate::go_bridge::goWasmSetMixFetchRequestTimeout; +use crate::request_writer::RequestWriter; +use crate::socks_helpers::{socks5_connect_request, socks5_data_request}; +use crate::{config, RequestId}; +use js_sys::Promise; +use nym_socks5_requests::RemoteAddress; +use wasm_bindgen::prelude::*; +use wasm_bindgen_futures::future_to_promise; +use wasm_client_core::client::base_client::{BaseClientBuilder, ClientInput, ClientOutput}; +use wasm_client_core::client::inbound_messages::InputMessage; +use wasm_client_core::helpers::setup_gateway_from_api; +use wasm_client_core::init::GatewaySetup; +use wasm_client_core::nym_task::connections::TransmissionLane; +use wasm_client_core::nym_task::TaskManager; +use wasm_client_core::storage::core_client_traits::FullWasmClientStorage; +use wasm_client_core::storage::ClientStorage; +use wasm_client_core::{IdentityKey, QueryReqwestRpcNyxdClient, Recipient}; +use wasm_utils::console_log; +use wasm_utils::error::PromisableResult; + +#[wasm_bindgen] +pub struct MixFetchClient { + mix_fetch_config: config::MixFetch, + + self_address: Recipient, + + client_input: ClientInput, + + requests: ActiveRequests, + + // even though we don't use graceful shutdowns, other components rely on existence of this struct + // and if it's dropped, everything will start going offline + _task_manager: TaskManager, +} + +#[wasm_bindgen] +pub struct MixFetchClientBuilder { + config: MixFetchConfig, + preferred_gateway: Option, + + storage_passphrase: Option, +} + +#[wasm_bindgen] +impl MixFetchClientBuilder { + #[wasm_bindgen(constructor)] + pub fn new( + config: MixFetchConfig, + preferred_gateway: Option, + storage_passphrase: Option, + ) -> Self { + MixFetchClientBuilder { + config, + preferred_gateway, + storage_passphrase, + } + } + + fn initialise_storage( + config: &MixFetchConfig, + base_storage: ClientStorage, + ) -> FullWasmClientStorage { + FullWasmClientStorage::new(&config.base, base_storage) + } + + fn start_reconstructor(client_output: ClientOutput, requests: ActiveRequests) { + RequestWriter::new(client_output, requests).start() + } + + // TODO: combine with normal wasm client + async fn start_client_async(mut self) -> Result { + console_log!("Starting the mix fetch client"); + + let timeout_ms = self.config.mix_fetch.debug.request_timeout.as_millis(); + if timeout_ms > u32::MAX as u128 { + return Err(MixFetchError::InvalidTimeoutValue { timeout_ms }); + } + goWasmSetMixFetchRequestTimeout(timeout_ms as u32); + + let nym_api_endpoints = self.config.base.client.nym_api_urls.clone(); + + // TODO: this will have to be re-used for surbs. but this is a problem for another PR. + let client_store = + ClientStorage::new_async(&self.config.base.client.id, self.storage_passphrase.take()) + .await?; + + let user_chosen = self.preferred_gateway.clone(); + let init_res = + setup_gateway_from_api(&client_store, user_chosen, &nym_api_endpoints).await?; + let storage = Self::initialise_storage(&self.config, client_store); + + let mut base_builder = BaseClientBuilder::::new( + &self.config.base, + storage, + None, + ); + if let Some(authenticated_ephemeral_client) = init_res.authenticated_ephemeral_client { + base_builder = base_builder.with_gateway_setup(GatewaySetup::ReuseConnection { + authenticated_ephemeral_client, + details: init_res.details, + }); + } + let mut started_client = base_builder.start_base().await?; + + let self_address = started_client.address; + + let active_requests = ActiveRequests::default(); + + let client_input = started_client.client_input.register_producer(); + let client_output = started_client.client_output.register_consumer(); + + Self::start_reconstructor(client_output, active_requests.clone()); + + Ok(MixFetchClient { + mix_fetch_config: self.config.mix_fetch, + self_address, + client_input, + requests: active_requests, + _task_manager: started_client.task_manager, + }) + } +} + +#[wasm_bindgen] +impl MixFetchClient { + pub(crate) async fn new_async( + config: MixFetchConfig, + preferred_gateway: Option, + storage_passphrase: Option, + ) -> Result { + MixFetchClientBuilder::new(config, preferred_gateway, storage_passphrase) + .start_client_async() + .await + } + + #[wasm_bindgen(constructor)] + #[allow(clippy::new_ret_no_self)] + pub fn new( + config: MixFetchConfig, + preferred_gateway: Option, + storage_passphrase: Option, + ) -> Promise { + future_to_promise(async move { + Self::new_async(config, preferred_gateway, storage_passphrase) + .await + .into_promise_result() + }) + } + + pub fn self_address(&self) -> String { + self.self_address.to_string() + } + + async fn send_socks_connect( + &self, + request_id: RequestId, + target: RemoteAddress, + ) -> Result<(), MixFetchError> { + let raw_conn_req = socks5_connect_request(request_id, target, self.self_address); + let lane = TransmissionLane::ConnectionId(request_id); + let input = InputMessage::new_regular( + self.mix_fetch_config.network_requester_address, + raw_conn_req, + lane, + None, + ); + + // the expect here is fine as it implies an unrecoverable failure since one of the client core + // tasks has terminated + self.client_input + .input_sender + .send(input) + .await + .expect("the client has stopped listening for requests"); + + Ok(()) + } + + async fn send_socks_data( + &self, + request_id: RequestId, + local_closed: bool, + message_sequence: u64, + data: Vec, + ) -> Result<(), MixFetchError> { + let raw_send_req = socks5_data_request(request_id, local_closed, message_sequence, data); + let lane = TransmissionLane::ConnectionId(request_id); + let input = InputMessage::new_regular( + self.mix_fetch_config.network_requester_address, + raw_send_req, + lane, + None, + ); + + // the expect here is fine as it implies an unrecoverable failure since one of the client core + // tasks has terminated + self.client_input + .input_sender + .send(input) + .await + .expect("the client has stopped listening for requests"); + + Ok(()) + } + + pub(crate) async fn connect_to_mixnet( + &self, + target: String, + ) -> Result { + let request_id = self.requests.start_new().await; + self.send_socks_connect(request_id, target).await?; + + Ok(request_id) + } + + pub(crate) async fn forward_request_content( + &self, + request_id: RequestId, + data: Vec, + ) -> Result<(), MixFetchError> { + let seq = self + .requests + .get_sending_sequence(request_id) + .await + .ok_or(MixFetchError::AbortedRequest { request_id })?; + + self.send_socks_data(request_id, false, seq, data).await + } + + pub(crate) async fn close_local_socket( + &self, + request_id: RequestId, + ) -> Result<(), MixFetchError> { + let seq = self + .requests + .get_sending_sequence(request_id) + .await + .ok_or(MixFetchError::AbortedRequest { request_id })?; + + self.send_socks_data(request_id, true, seq, Vec::new()) + .await + } + + pub(crate) async fn disconnect_from_mixnet( + &self, + request_id: RequestId, + ) -> Result<(), MixFetchError> { + self.close_local_socket(request_id).await?; + self.requests.finish(request_id).await; + Ok(()) + } +} diff --git a/wasm/mix-fetch/src/config.rs b/wasm/mix-fetch/src/config.rs new file mode 100644 index 0000000000..3d8087e169 --- /dev/null +++ b/wasm/mix-fetch/src/config.rs @@ -0,0 +1,153 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +// due to expansion of #[wasm_bindgen] macro on `MixFetch` Config struct +#![allow(clippy::drop_non_drop)] + +use crate::error::MixFetchError; +use serde::{Deserialize, Serialize}; +use std::time::Duration; +use tsify::Tsify; +use wasm_bindgen::prelude::*; +use wasm_client_core::config::{new_base_client_config, BaseClientConfig, ConfigDebug, DebugWasm}; +use wasm_client_core::helpers::parse_recipient; +use wasm_client_core::Recipient; + +const DEFAULT_MIX_FETCH_TIMEOUT: Duration = Duration::from_secs(5); +const DEFAULT_MIX_FETCH_ID: &str = "_default-nym-mix-fetch"; +const MIX_FETCH_CLIENT_ID_PREFIX: &str = "mix-fetch"; + +fn make_mix_fetch_id(id: Option) -> String { + if let Some(provided) = id { + format!("{MIX_FETCH_CLIENT_ID_PREFIX}-{provided}") + } else { + DEFAULT_MIX_FETCH_ID.to_string() + } +} + +#[wasm_bindgen] +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct MixFetchConfig { + pub(crate) base: BaseClientConfig, + + pub(crate) mix_fetch: MixFetch, +} + +#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct MixFetchConfigOpts { + #[tsify(optional)] + pub id: Option, + + #[tsify(optional)] + pub nym_api: Option, + + #[tsify(optional)] + pub nyxd: Option, + + #[tsify(optional)] + pub debug: Option, +} + +#[wasm_bindgen] +impl MixFetchConfig { + #[wasm_bindgen(constructor)] + pub fn new( + network_requester_address: String, + opts: Option, + ) -> Result { + let version = env!("CARGO_PKG_VERSION").to_string(); + if let Some(opts) = opts { + Ok(MixFetchConfig { + base: new_base_client_config( + make_mix_fetch_id(opts.id), + version, + opts.nym_api, + opts.nyxd, + opts.debug, + )?, + mix_fetch: MixFetch::new(network_requester_address)?, + }) + } else { + Ok(MixFetchConfig { + base: BaseClientConfig::new(make_mix_fetch_id(None), version), + mix_fetch: MixFetch::new(network_requester_address)?, + }) + } + } +} + +#[wasm_bindgen] +impl MixFetchConfig { + pub fn with_mix_fetch_timeout(mut self, timeout_ms: u32) -> Self { + self.mix_fetch.debug.request_timeout = Duration::from_millis(timeout_ms as u64); + self + } +} + +impl MixFetchConfig { + pub fn override_debug>(&mut self, debug: D) { + self.base.debug = debug.into(); + } + + pub fn override_mix_fetch_debug>(&mut self, debug: D) { + self.mix_fetch.debug = debug.into(); + } +} + +#[wasm_bindgen] +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct MixFetch { + pub(crate) network_requester_address: Recipient, + + #[serde(default)] + pub(crate) debug: MixFetchDebug, +} + +impl MixFetch { + pub(crate) fn new(network_requester_address: String) -> Result { + Ok(MixFetch { + network_requester_address: parse_recipient(&network_requester_address)?, + debug: Default::default(), + }) + } +} + +#[wasm_bindgen] +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct MixFetchDebug { + pub(crate) request_timeout: Duration, +} + +impl Default for MixFetchDebug { + fn default() -> Self { + MixFetchDebug { + request_timeout: DEFAULT_MIX_FETCH_TIMEOUT, + } + } +} + +#[derive(Tsify, Debug, Copy, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct MixFetchDebugOverride { + #[tsify(optional)] + pub request_timeout_ms: Option, +} + +impl From for MixFetchDebug { + fn from(value: MixFetchDebugOverride) -> Self { + let def = MixFetchDebug::default(); + + MixFetchDebug { + request_timeout: value + .request_timeout_ms + .map(|d| Duration::from_millis(d as u64)) + .unwrap_or(def.request_timeout), + } + } +} diff --git a/wasm/mix-fetch/src/error.rs b/wasm/mix-fetch/src/error.rs new file mode 100644 index 0000000000..5333f1849c --- /dev/null +++ b/wasm/mix-fetch/src/error.rs @@ -0,0 +1,90 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::harbourmaster::HarbourMasterApiError; +use crate::RequestId; +use js_sys::Promise; +use nym_ordered_buffer::OrderedMessageError; +use nym_socks5_requests::ConnectionError; +use thiserror::Error; +use wasm_client_core::error::WasmCoreError; +use wasm_client_core::ClientCoreError; +use wasm_utils::wasm_error; + +#[derive(Debug, Error)] +pub enum MixFetchError { + #[error(transparent)] + CoreError { + #[from] + source: WasmCoreError, + }, + + #[error("no public network requesters are not available on this network")] + NoNetworkRequesters, + + #[error("could not query for the service providers: {source}")] + HarbourmasterError { + #[from] + source: HarbourMasterApiError, + }, + + #[error("failed to parse mix fetch config options: {source}")] + MalformedConfigOptions { + #[from] + source: serde_wasm_bindgen::Error, + }, + + #[error("mix fetch hasn't been initialised")] + Uninitialised, + + #[error("mix fetch has already been initialised before")] + AlreadyInitialised, + + #[error("provided mix fetch url wasn't a string")] + NotStringMixFetchUrl, + + #[error("request {request_id} has been aborted")] + AbortedRequest { request_id: RequestId }, + + #[error("provided mix fetch url was malformed: {0}")] + MalformedMixFetchUrl(#[from] url::ParseError), + + // the maximum value is u32::MAX which equals to over 49days, which is MORE than enough + #[error("attempted to set request timeout to {timeout_ms}ms")] + InvalidTimeoutValue { timeout_ms: u128 }, + + #[error("network requester has rejected our request: {network_requester_message}")] + ConnectionError { network_requester_message: String }, + + #[error("failed to reconstruct the response: {source}")] + MalformedData { + #[from] + source: OrderedMessageError, + }, + + #[error("received multiple messages about the remote socket being closed for request {request}. The first was on seq {first} and the other on {other}")] + DuplicateSocketClosure { + request: RequestId, + first: u64, + other: u64, + }, +} + +// I dislike this so much - there must be a better way. +impl From for MixFetchError { + fn from(value: ClientCoreError) -> Self { + MixFetchError::CoreError { + source: WasmCoreError::BaseClientError { source: value }, + } + } +} + +impl From for MixFetchError { + fn from(value: ConnectionError) -> Self { + MixFetchError::ConnectionError { + network_requester_message: value.network_requester_error, + } + } +} + +wasm_error!(MixFetchError); diff --git a/wasm/mix-fetch/src/fetch.rs b/wasm/mix-fetch/src/fetch.rs new file mode 100644 index 0000000000..2e2adef992 --- /dev/null +++ b/wasm/mix-fetch/src/fetch.rs @@ -0,0 +1,145 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::client::MixFetchClient; +use crate::config::{MixFetchConfig, MixFetchConfigOpts, MixFetchDebugOverride}; +use crate::error::MixFetchError; +use crate::helpers::get_network_requester; +use js_sys::Promise; +use serde::{Deserialize, Serialize}; +use std::sync::OnceLock; +use tsify::Tsify; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::JsValue; +use wasm_bindgen_futures::future_to_promise; +use wasm_client_core::config::r#override::DebugWasmOverride; +use wasm_utils::console_log; +use wasm_utils::error::PromisableResultError; + +pub type RequestId = u64; + +pub(super) static MIX_FETCH: OnceLock = OnceLock::new(); + +#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct MixFetchOpts { + // ideally we'd have used the `IdentityKey` type alias, but that'd be extremely annoying to get working in TS + #[serde(flatten)] + pub(crate) base: MixFetchOptsSimple, + + #[tsify(optional)] + pub(crate) client_id: Option, + + #[tsify(optional)] + pub(crate) nym_api_url: Option, + + // currently not used, but will be required once we have coconut + #[tsify(optional)] + pub(crate) nyxd_url: Option, + + #[tsify(optional)] + pub(crate) client_override: Option, + + #[tsify(optional)] + pub(crate) mix_fetch_override: Option, +} + +#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct MixFetchOptsSimple { + // ideally we'd have used the `IdentityKey` type alias, but that'd be extremely annoying to get working in TS + #[tsify(optional)] + pub(crate) preferred_gateway: Option, + + #[tsify(optional)] + pub(crate) preferred_network_requester: Option, + + #[tsify(optional)] + pub(crate) storage_passphrase: Option, +} + +impl<'a> From<&'a MixFetchOpts> for MixFetchConfigOpts { + fn from(value: &'a MixFetchOpts) -> Self { + MixFetchConfigOpts { + id: value.client_id.as_ref().map(|v| v.to_owned()), + nym_api: value.nym_api_url.as_ref().map(|v| v.to_owned()), + nyxd: value.nyxd_url.as_ref().map(|v| v.to_owned()), + debug: value.client_override.as_ref().map(|&v| v.into()), + } + } +} + +// TODO: in the future make the network requester address optional once there exists some API for obtaining NR addresses +#[wasm_bindgen(js_name = setupMixFetch)] +pub fn setup_mix_fetch(opts: MixFetchOpts) -> Promise { + if MIX_FETCH.get().is_some() { + return MixFetchError::AlreadyInitialised.into_rejected_promise(); + } + + // if nym api was overridden, it means we're not using mainnet and we don't have harbourmaster url + // for anything that's not mainnet + if opts.nym_api_url.is_some() && opts.base.preferred_network_requester.is_none() { + return MixFetchError::NoNetworkRequesters.into_rejected_promise(); + } + + future_to_promise(async move { + let network_requester_address = + get_network_requester(opts.base.preferred_network_requester.clone()) + .await + .map_promise_err()?; + + console_log!("going to use {network_requester_address} network requester"); + + let mut config = MixFetchConfig::new(network_requester_address, Some((&opts).into())) + .map_promise_err()?; + if let Some(dbg) = opts.client_override { + config.override_debug(dbg); + } + + if let Some(dbg) = opts.mix_fetch_override { + config.override_mix_fetch_debug(dbg) + } + + setup_mix_fetch_async(config, opts.base) + .await + .map(|_| JsValue::undefined()) + .map_promise_err() + }) +} + +#[wasm_bindgen(js_name = setupMixFetchWithConfig)] +pub fn setup_mix_fetch_with_config(config: MixFetchConfig, opts: MixFetchOptsSimple) -> Promise { + if MIX_FETCH.get().is_some() { + return MixFetchError::AlreadyInitialised.into_rejected_promise(); + } + + future_to_promise(async move { + setup_mix_fetch_async(config, opts) + .await + .map(|_| JsValue::undefined()) + .map_promise_err() + }) +} + +pub(super) fn set_mix_fetch_client(mix_fetch_client: MixFetchClient) -> Result<(), MixFetchError> { + MIX_FETCH + .set(mix_fetch_client) + .map_err(|_| MixFetchError::AlreadyInitialised) +} + +pub(super) fn mix_fetch_client() -> Result<&'static MixFetchClient, MixFetchError> { + MIX_FETCH.get().ok_or(MixFetchError::Uninitialised) +} + +async fn setup_mix_fetch_async( + config: MixFetchConfig, + opts: MixFetchOptsSimple, +) -> Result<(), MixFetchError> { + let preferred_gateway = opts.preferred_gateway; + let storage_passphrase = opts.storage_passphrase; + let client = MixFetchClient::new_async(config, preferred_gateway, storage_passphrase).await?; + set_mix_fetch_client(client)?; + Ok(()) +} diff --git a/wasm/mix-fetch/src/go_bridge.rs b/wasm/mix-fetch/src/go_bridge.rs new file mode 100644 index 0000000000..d9acd8d37c --- /dev/null +++ b/wasm/mix-fetch/src/go_bridge.rs @@ -0,0 +1,99 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::{mix_fetch_client, MIX_FETCH}; +use js_sys::Promise; +use wasm_bindgen::prelude::*; +use wasm_bindgen::JsValue; +use wasm_bindgen_futures::future_to_promise; +use wasm_utils::error::{simple_rejected_promise, PromisableResult}; + +/// Called by go runtime whenever local connection produces any data that has to be sent to the remote. +// +// TODO: currently this requires weird workaround to put it on the global object inside JS... +// need some help from @MS to fix that up. +// this is not expected to be called but a normal user under any circumstances +// (perhaps it should be moved somewhere outside the global object then? +#[wasm_bindgen] +pub fn send_client_data(stringified_request_id: String, data: Vec) -> Promise { + let request_id = match stringified_request_id.parse() { + Ok(id) => id, + Err(err) => { + return simple_rejected_promise(format!("failed to parse received request: {err}")) + } + }; + + future_to_promise(async move { + // this error should be impossible in normal use + // (unless, of course, user is messing around, but then it's their fault for this panic) + let mix_fetch = mix_fetch_client().expect("mix fetch hasn't been setup"); + mix_fetch.forward_request_content(request_id, data).await?; + Ok(JsValue::undefined()) + }) +} + +/// Called by go runtime whenever it establishes new connection +/// (whether the initial one or on any redirection attempt). +// +// TODO: currently this requires weird workaround to put it on the global object inside JS... +// need some help from @MS to fix that up. +// this is not expected to be called but a normal user under any circumstances +// (perhaps it should be moved somewhere outside the global object then? +#[wasm_bindgen] +pub fn start_new_mixnet_connection(target: String) -> Promise { + future_to_promise(async move { + // this error should be impossible in normal use + // (unless, of course, user is messing around, but then it's their fault for this panic) + let mix_fetch = mix_fetch_client().expect("mix fetch hasn't been setup"); + mix_fetch + .connect_to_mixnet(target) + .await + .map(|request_id| request_id.to_string()) + .into_promise_result() + }) +} + +#[wasm_bindgen] +pub fn mix_fetch_initialised() -> bool { + MIX_FETCH.get().is_some() +} + +/// Called by go runtime whenever it's done with a connection +// +// TODO: currently this requires weird workaround to put it on the global object inside JS... +// need some help from @MS to fix that up. +// this is not expected to be called but a normal user under any circumstances +// (perhaps it should be moved somewhere outside the global object then? +#[wasm_bindgen] +pub fn finish_mixnet_connection(stringified_request_id: String) -> Promise { + let request_id = match stringified_request_id.parse() { + Ok(id) => id, + Err(err) => { + return simple_rejected_promise(format!("failed to parse received request: {err}")) + } + }; + + future_to_promise(async move { + // this error should be impossible in normal use + // (unless, of course, user is messing around, but then it's their fault for this panic) + let mix_fetch = mix_fetch_client().expect("mix fetch hasn't been setup"); + mix_fetch.disconnect_from_mixnet(request_id).await?; + Ok(JsValue::undefined()) + }) +} + +// note the namespace (defined in wasm/main.go) +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_namespace = __go_rs_bridge__)] + pub(crate) fn goWasmInjectServerData(raw_connection_id: String, data: Vec); + + #[wasm_bindgen(js_namespace = __go_rs_bridge__)] + pub(crate) fn goWasmCloseRemoteSocket(raw_connection_id: String); + + #[wasm_bindgen(js_namespace = __go_rs_bridge__)] + pub(crate) fn goWasmInjectConnError(raw_connection_id: String, error_msg: String); + + #[wasm_bindgen(js_namespace = __go_rs_bridge__)] + pub(crate) fn goWasmSetMixFetchRequestTimeout(timeout_ms: u32); +} diff --git a/wasm/mix-fetch/src/harbourmaster.rs b/wasm/mix-fetch/src/harbourmaster.rs new file mode 100644 index 0000000000..862f6a316a --- /dev/null +++ b/wasm/mix-fetch/src/harbourmaster.rs @@ -0,0 +1,141 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +// this exists inside mix-fetch rather than being made into repo-wide library since it's a temporary solution +// until the API is finalised and endpoints are moved to nym-api + +use reqwest::{IntoUrl, Response, StatusCode}; +use serde::Deserialize; +use thiserror::Error; +use url::Url; + +mod routes { + pub const API_VERSION: &str = "v1"; + + pub const SERVICES: &str = "services"; + + pub const NEW: &str = "new"; +} + +// most of it is copied from the nym-api client +type PathSegments<'a> = &'a [&'a str]; +type Params<'a, K, V> = &'a [(K, V)]; + +const NO_PARAMS: Params<'_, &'_ str, &'_ str> = &[]; + +#[derive(Debug, Error)] +pub enum HarbourMasterApiError { + #[error("there was an issue with the REST request: {source}")] + ReqwestClientError { + #[from] + source: reqwest::Error, + }, + + #[error("not found")] + NotFound, + + #[error("request failed with error message: {0}")] + GenericRequestFailure(String), +} + +pub struct Client { + url: Url, + reqwest_client: reqwest::Client, +} + +impl Client { + pub fn new(url: U) -> Result { + let reqwest_client = reqwest::Client::new(); + Ok(Self { + url: url.into_url()?, + reqwest_client, + }) + } + + async fn send_get_request( + &self, + path: PathSegments<'_>, + params: Params<'_, K, V>, + ) -> Result + where + K: AsRef, + V: AsRef, + { + let url = create_api_url(&self.url, path, params); + Ok(self.reqwest_client.get(url).send().await?) + } + + async fn query_harbourmaster( + &self, + path: PathSegments<'_>, + params: Params<'_, K, V>, + ) -> Result + where + for<'a> T: Deserialize<'a>, + K: AsRef, + V: AsRef, + { + let res = self.send_get_request(path, params).await?; + if res.status().is_success() { + Ok(res.json().await?) + } else if res.status() == StatusCode::NOT_FOUND { + Err(HarbourMasterApiError::NotFound) + } else { + Err(HarbourMasterApiError::GenericRequestFailure( + res.text().await?, + )) + } + } + + // since it's a temporary thing don't worry about paging. + pub async fn get_services_new(&self) -> Result, HarbourMasterApiError> { + self.query_harbourmaster( + &[routes::API_VERSION, routes::SERVICES, routes::NEW], + NO_PARAMS, + ) + .await + } +} + +fn create_api_url, V: AsRef>( + base: &Url, + segments: PathSegments<'_>, + params: Params<'_, K, V>, +) -> Url { + let mut url = base.clone(); + let mut path_segments = url + .path_segments_mut() + .expect("provided validator url does not have a base!"); + for segment in segments { + let segment = segment.strip_prefix('/').unwrap_or(segment); + let segment = segment.strip_suffix('/').unwrap_or(segment); + + path_segments.push(segment); + } + drop(path_segments); + + if !params.is_empty() { + url.query_pairs_mut().extend_pairs(params); + } + + url +} + +// https://gitlab.nymte.ch/nym/shipyard-test-and-earn/-/blob/main/harbour-master/src/http/mod.rs#L13 +#[derive(Debug, Deserialize)] +pub struct PagedResult { + pub page: u32, + pub size: u32, + pub total: i32, + pub items: Vec, +} + +// https://gitlab.nymte.ch/nym/shipyard-test-and-earn/-/blob/main/harbour-master/src/http/services.rs#L32 +#[derive(Debug, Deserialize)] +pub struct ServiceNew { + pub service_provider_client_id: String, + pub ip_address: String, + pub last_successful_ping_utc: String, + pub last_updated_utc: String, + pub routing_score: f32, +} diff --git a/wasm/mix-fetch/src/helpers.rs b/wasm/mix-fetch/src/helpers.rs new file mode 100644 index 0000000000..aee8cb1e7f --- /dev/null +++ b/wasm/mix-fetch/src/helpers.rs @@ -0,0 +1,36 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::error::MixFetchError; +use crate::harbourmaster; +use rand::seq::SliceRandom; +use rand::thread_rng; +use wasm_utils::console_log; + +// since this client is temporary (and will be properly integrated into nym-api eventually), +// we're using hardcoded URL for mainnet +const HARBOUR_MASTER: &str = "https://harbourmaster.nymtech.net"; + +pub(crate) async fn get_network_requester( + preferred: Option, +) -> Result { + if let Some(sp) = preferred { + return Ok(sp); + } + + let client = harbourmaster::Client::new(HARBOUR_MASTER)?; + let providers = client.get_services_new().await?; + console_log!( + "obtained list of {} service providers on the network", + providers.items.len() + ); + + // this will only return a `None` if the list is empty + let mut rng = thread_rng(); + providers + .items + .choose(&mut rng) + .map(|service| &service.service_provider_client_id) + .cloned() + .ok_or(MixFetchError::NoNetworkRequesters) +} diff --git a/wasm/mix-fetch/src/lib.rs b/wasm/mix-fetch/src/lib.rs new file mode 100644 index 0000000000..f2e9b695c5 --- /dev/null +++ b/wasm/mix-fetch/src/lib.rs @@ -0,0 +1,34 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +#[cfg(target_arch = "wasm32")] +mod active_requests; +#[cfg(target_arch = "wasm32")] +mod client; +#[cfg(target_arch = "wasm32")] +mod config; +#[cfg(target_arch = "wasm32")] +pub mod error; +#[cfg(target_arch = "wasm32")] +mod fetch; +#[cfg(target_arch = "wasm32")] +mod go_bridge; +#[cfg(target_arch = "wasm32")] +mod harbourmaster; +#[cfg(target_arch = "wasm32")] +mod helpers; +#[cfg(target_arch = "wasm32")] +mod request_writer; +#[cfg(target_arch = "wasm32")] +mod socks_helpers; + +#[cfg(target_arch = "wasm32")] +pub(crate) use fetch::{mix_fetch_client, RequestId, MIX_FETCH}; +#[cfg(target_arch = "wasm32")] +use wasm_bindgen::prelude::*; + +#[wasm_bindgen(start)] +#[cfg(target_arch = "wasm32")] +pub fn main() { + wasm_utils::console_log!("[rust main]: rust module loaded") +} diff --git a/wasm/mix-fetch/src/request_writer.rs b/wasm/mix-fetch/src/request_writer.rs new file mode 100644 index 0000000000..7a91c93a61 --- /dev/null +++ b/wasm/mix-fetch/src/request_writer.rs @@ -0,0 +1,83 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::active_requests::ActiveRequests; +use futures::channel::mpsc; +use futures::StreamExt; +use nym_service_providers_common::interface::ResponseContent; +use nym_socks5_requests::{Socks5ProviderResponse, Socks5ResponseContent}; +use wasm_bindgen_futures::spawn_local; +use wasm_client_core::client::base_client::ClientOutput; +use wasm_client_core::client::received_buffer::{ + ReceivedBufferMessage, ReconstructedMessagesReceiver, +}; +use wasm_client_core::ReconstructedMessage; +use wasm_utils::console_error; + +pub(crate) struct RequestWriter { + reconstructed_receiver: ReconstructedMessagesReceiver, + requests: ActiveRequests, +} + +impl RequestWriter { + pub(crate) fn new(client_output: ClientOutput, requests: ActiveRequests) -> Self { + // register our output + let (reconstructed_sender, reconstructed_receiver) = mpsc::unbounded(); + + // tell the buffer to start sending stuff to us + client_output + .received_buffer_request_sender + .unbounded_send(ReceivedBufferMessage::ReceiverAnnounce( + reconstructed_sender, + )) + .expect("the buffer request failed!"); + + RequestWriter { + reconstructed_receiver, + requests, + } + } + + async fn handle_reconstructed(&mut self, reconstructed_message: ReconstructedMessage) { + let (msg, tag) = reconstructed_message.into_inner(); + + if tag.is_some() { + console_error!( + "received a response with an anonymous sender tag - this is highly unexpected!" + ); + } + + match Socks5ProviderResponse::try_from_bytes(&msg) { + Err(err) => { + console_error!("failed to deserialize provider response. it was most likely not a response to our fetch: {err}") + } + Ok(provider_response) => match provider_response.content { + ResponseContent::Control(control) => { + console_error!("received a provider control response even though we didnt send any requests! - {control:#?}") + } + ResponseContent::ProviderData(data_response) => match data_response.content { + Socks5ResponseContent::ConnectionError(err) => { + self.requests.reject(err.connection_id, err.into()).await; + } + Socks5ResponseContent::Query(query) => { + console_error!("received a provider query response even though we didn't send any queries! - {query:#?}") + } + Socks5ResponseContent::NetworkData { content } => { + self.requests.try_send_data_to_go(content).await; + } + }, + }, + } + } + + pub(crate) fn start(mut self) { + spawn_local(async move { + while let Some(reconstructed) = self.reconstructed_receiver.next().await { + for reconstructed_msg in reconstructed { + self.handle_reconstructed(reconstructed_msg).await + } + } + console_error!("we stopped receiving reconstructed messages!") + }) + } +} diff --git a/wasm/mix-fetch/src/socks_helpers.rs b/wasm/mix-fetch/src/socks_helpers.rs new file mode 100644 index 0000000000..827e8ac120 --- /dev/null +++ b/wasm/mix-fetch/src/socks_helpers.rs @@ -0,0 +1,49 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use nym_service_providers_common::interface::ProviderInterfaceVersion; +use nym_socks5_requests::{ + ConnectionId, RemoteAddress, SocketData, Socks5ProtocolVersion, Socks5ProviderRequest, +}; +use wasm_client_core::Recipient; + +pub(crate) const PROVIDER_INTERFACE_VERSION: ProviderInterfaceVersion = + ProviderInterfaceVersion::new_current(); +pub(crate) const SOCKS5_PROTOCOL_VERSION: Socks5ProtocolVersion = + Socks5ProtocolVersion::new_current(); + +// for now explicitly attach return address, we can worry about surbs later +pub(crate) fn socks5_connect_request( + conn_id: ConnectionId, + remote_addr: RemoteAddress, + return_address: Recipient, +) -> Vec { + // Create SOCKS connect request + let request_content = nym_socks5_requests::request::Socks5Request::new_connect( + SOCKS5_PROTOCOL_VERSION, + conn_id, + remote_addr, + Some(return_address), + ); + + // and wrap it in provider request + Socks5ProviderRequest::new_provider_data(PROVIDER_INTERFACE_VERSION, request_content) + .into_bytes() +} + +pub(crate) fn socks5_data_request( + conn_id: ConnectionId, + local_closed: bool, + message_sequence: u64, + data: Vec, +) -> Vec { + // Create SOCKS send request + let request_content = nym_socks5_requests::request::Socks5Request::new_send( + SOCKS5_PROTOCOL_VERSION, + SocketData::new(message_sequence, conn_id, local_closed, data), + ); + + // and wrap it in provider request + Socks5ProviderRequest::new_provider_data(PROVIDER_INTERFACE_VERSION, request_content) + .into_bytes() +} diff --git a/wasm/node-tester/.cargo/config.toml b/wasm/node-tester/.cargo/config.toml new file mode 100644 index 0000000000..bdbe517658 --- /dev/null +++ b/wasm/node-tester/.cargo/config.toml @@ -0,0 +1,3 @@ +[build] +target = "wasm32-unknown-unknown" +target_arch = "wasm32" diff --git a/wasm/node-tester/Cargo.toml b/wasm/node-tester/Cargo.toml new file mode 100644 index 0000000000..b5a59e1641 --- /dev/null +++ b/wasm/node-tester/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "nym-node-tester-wasm" +authors = ["Jedrzej Stuczynski "] +version = "1.2.0-rc.2" +edition = "2021" +keywords = ["nym", "sphinx", "webassembly", "privacy", "tester"] +license = "Apache-2.0" +repository = "https://github.com/nymtech/nym" +rust-version = "1.56" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +futures = { workspace = true } +js-sys = { workspace = true } +rand = { version = "0.7.3", features = ["wasm-bindgen"] } +serde = { workspace = true, features = ["derive"] } +serde-wasm-bindgen = { workspace = true } +tokio = { workspace = true, features = ["sync"] } +wasm-bindgen = { workspace = true } +wasm-bindgen-futures = { workspace = true } +thiserror = { workspace = true } +tsify = { workspace = true, features = ["js"] } + +wasmtimer = { workspace = true } + +nym-node-tester-utils = { path = "../../common/node-tester-utils" } +wasm-client-core = { path = "../../common/wasm/client-core" } +wasm-utils = { path = "../../common/wasm/utils" } + +[package.metadata.wasm-pack.profile.release] +wasm-opt = false + +[profile.release] +lto = true +opt-level = 'z' diff --git a/wasm/node-tester/Makefile b/wasm/node-tester/Makefile new file mode 100644 index 0000000000..3c8440c851 --- /dev/null +++ b/wasm/node-tester/Makefile @@ -0,0 +1,3 @@ +build: + wasm-pack build --scope nymproject --target web --out-dir ../../dist/wasm/node-tester + wasm-opt -Oz -o ../../dist/wasm/node-tester/nym_node_tester_wasm_bg.wasm ../../dist/wasm/node-tester/nym_node_tester_wasm_bg.wasm diff --git a/wasm/node-tester/internal-dev/.gitignore b/wasm/node-tester/internal-dev/.gitignore new file mode 100644 index 0000000000..f06235c460 --- /dev/null +++ b/wasm/node-tester/internal-dev/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist diff --git a/wasm/node-tester/internal-dev/bootstrap.js b/wasm/node-tester/internal-dev/bootstrap.js new file mode 100644 index 0000000000..a017926b28 --- /dev/null +++ b/wasm/node-tester/internal-dev/bootstrap.js @@ -0,0 +1,5 @@ +// A dependency graph that contains any wasm must all be imported +// asynchronously. This `bootstrap.js` file does the single async import, so +// that no one else needs to worry about it again. +import('./index.js') + .catch(e => console.error('Error importing `index.js`:', e)); diff --git a/wasm/node-tester/internal-dev/index.html b/wasm/node-tester/internal-dev/index.html new file mode 100644 index 0000000000..8182be7ab6 --- /dev/null +++ b/wasm/node-tester/internal-dev/index.html @@ -0,0 +1,44 @@ + + + + + + + Nym WebAssembly Demo + + + + +

+ +

+ +

+ +

+

+ +

+

+ +

+ +
+ + + +
+ + +

Send messages from your browser, through the mixnet, and to the recipient using the "send" button.

+

Sent messages show in blue, received + messages show in green.

+ +
+

+ +

+ + + + \ No newline at end of file diff --git a/wasm/node-tester/internal-dev/index.js b/wasm/node-tester/internal-dev/index.js new file mode 100644 index 0000000000..0ff5c3a191 --- /dev/null +++ b/wasm/node-tester/internal-dev/index.js @@ -0,0 +1,173 @@ +// Copyright 2020-2023 Nym Technologies SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +class WebWorkerClient { + worker = null; + + constructor() { + this.worker = new Worker('./worker.js'); + + this.worker.onmessage = (ev) => { + if (ev.data && ev.data.kind) { + switch (ev.data.kind) { + case 'Ready': + const {selfAddress} = ev.data.args; + displaySenderAddress(selfAddress); + break; + case 'ReceiveMessage': + const {message, senderTag, isTestPacket } = ev.data.args; + displayReceived(message, senderTag, isTestPacket); + break; + case 'DisplayString': + const { rawString } = ev.data.args; + displayReceivedRawString(rawString) + break; + case 'DisableMagicTestButton': + const magicButton = document.querySelector('#magic-button'); + magicButton.setAttribute('disabled', "true") + break; + case 'DisplayTesterResults': + const {score, sentPackets, receivedPackets, receivedAcks, duplicatePackets, duplicateAcks} = ev.data.args; + const resultText = `Test score: ${score}. Sent ${sentPackets} packets. Received ${receivedPackets} packets and ${receivedAcks} acks back. We also got ${duplicatePackets} duplicate packets and ${duplicateAcks} duplicate acks.` + displayReceivedRawString(resultText) + break; + } + } + }; + } + + sendMessage = (message, recipient) => { + if (!this.worker) { + console.error('Could not send message because worker does not exist'); + return; + } + + this.worker.postMessage({ + kind: 'SendMessage', + args: { + message, recipient, + }, + }); + }; + + sendMagicPayload = (mixnodeIdentity) => { + if (!this.worker) { + console.error('Could not send message because worker does not exist'); + return; + } + + this.worker.postMessage({ + kind: 'MagicPayload', + args: { + mixnodeIdentity, + }, + }); + } +} + +let client = null; + +async function main() { + client = new WebWorkerClient(); + + const sendButton = document.querySelector('#send-button'); + sendButton.onclick = function () { + sendMessageTo(); + }; + + const magicButton = document.querySelector('#magic-button'); + magicButton.onclick = function () { + sendMagicPayload(); + } +} + +/** + * Create a Sphinx packet and send it to the mixnet through the gateway node. + * + * Message and recipient are taken from the values in the user interface. + * + */ +async function sendMessageTo() { + const message = document.getElementById('message').value; + const recipient = document.getElementById('recipient').value; + + await client.sendMessage(message, recipient); + displaySend(message); +} + +async function sendMagicPayload() { + const payload = document.getElementById('magic_payload').value; + await client.sendMagicPayload(payload) + + displaySend(`clicked the button and the payload is: ${payload}...`); +} + +/** + * Display messages that have been sent up the websocket. Colours them blue. + * + * @param {string} message + */ +function displaySend(message) { + let timestamp = new Date().toISOString().substr(11, 12); + + let sendDiv = document.createElement('div'); + let paragraph = document.createElement('p'); + paragraph.setAttribute('style', 'color: blue'); + let paragraphContent = document.createTextNode(timestamp + ' sent >>> ' + message); + paragraph.appendChild(paragraphContent); + + sendDiv.appendChild(paragraph); + document.getElementById('output').appendChild(sendDiv); +} + +/** + * Display received text messages in the browser. Colour them green. + * + * @param {Uint8Array} raw + */ +function displayReceived(raw, sender_tag, isTestPacket) { + let content = new TextDecoder().decode(raw); + if (sender_tag !== undefined) { + console.log("this message also contained some surbs from", sender_tag) + } + + if (isTestPacket) { + const decoded = JSON.parse(content) + content = `Received packet ${decoded.msg_id} / ${decoded.total_msgs} for node ${decoded.encoded_node_identity} (test: ${decoded.test_id})` + } + + displayReceivedRawString(content) +} + +function displayReceivedRawString(raw) { + let timestamp = new Date().toISOString().substr(11, 12); + let receivedDiv = document.createElement('div'); + let paragraph = document.createElement('p'); + paragraph.setAttribute('style', 'color: green'); + let paragraphContent = document.createTextNode(timestamp + ' received >>> ' + raw); + paragraph.appendChild(paragraphContent); + receivedDiv.appendChild(paragraph); + document.getElementById('output').appendChild(receivedDiv); +} + +/** + * Display the nymClient's sender address in the user interface + * + * @param {String} address + */ +function displaySenderAddress(address) { + document.getElementById('sender').value = address; +} + +main(); diff --git a/wasm/node-tester/internal-dev/package.json b/wasm/node-tester/internal-dev/package.json new file mode 100644 index 0000000000..c4f96d644c --- /dev/null +++ b/wasm/node-tester/internal-dev/package.json @@ -0,0 +1,40 @@ +{ + "name": "create-wasm-app", + "version": "0.1.0", + "description": "create an app to consume rust-generated wasm packages", + "main": "index.js", + "bin": { + "create-wasm-app": ".bin/create-wasm-app.js" + }, + "scripts": { + "build": "webpack --config webpack.config.js", + "build:wasm": "cd ../ && make wasm-build", + "start": "webpack-dev-server --port 8001" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/rustwasm/create-wasm-app.git" + }, + "keywords": [ + "webassembly", + "wasm", + "rust", + "webpack" + ], + "author": "Dave Hrycyszyn ", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/nymtech/nym/issues" + }, + "homepage": "https://nymtech.net/docs", + "devDependencies": { + "copy-webpack-plugin": "^11.0.0", + "hello-wasm-pack": "^0.1.0", + "webpack": "^5.70.0", + "webpack-cli": "^4.9.2", + "webpack-dev-server": "^4.7.4" + }, + "dependencies": { + "@nymproject/nym_node_tester_wasm": "file:../../../dist/wasm/node-tester" + } +} diff --git a/wasm/node-tester/internal-dev/webpack.config.js b/wasm/node-tester/internal-dev/webpack.config.js new file mode 100644 index 0000000000..2e7ec5ce87 --- /dev/null +++ b/wasm/node-tester/internal-dev/webpack.config.js @@ -0,0 +1,33 @@ +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const path = require('path'); + +module.exports = { + performance: { + hints: false, + maxEntrypointSize: 512000, + maxAssetSize: 512000 + }, + entry: { + bootstrap: './bootstrap.js', + worker: './worker.js', + }, + output: { + path: path.resolve(__dirname, 'dist'), + filename: '[name].js', + }, + mode: 'development', + // mode: 'production', + plugins: [ + new CopyWebpackPlugin({ + patterns: [ + 'index.html', + { + from: '../../../dist/wasm/node-tester/*.(js|wasm)', + to: '[name][ext]', + }, + ], + }), + + ], + experiments: { syncWebAssembly: true }, +}; diff --git a/wasm/node-tester/internal-dev/worker.js b/wasm/node-tester/internal-dev/worker.js new file mode 100644 index 0000000000..a06e7e8a8c --- /dev/null +++ b/wasm/node-tester/internal-dev/worker.js @@ -0,0 +1,152 @@ +// Copyright 2020-2023 Nym Technologies SA +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +const RUST_WASM_URL = "nym_node_tester_wasm_bg.wasm" + +importScripts('nym_node_tester_wasm.js'); + +console.log('Initializing worker'); + +// wasm_bindgen creates a global variable (with the exports attached) that is in scope after `importScripts` +const { + default_debug, + no_cover_debug, + NymNodeTester, + set_panic_hook, + currentNetworkTopology, +} = wasm_bindgen; + +let client = null; + +function dummyTopology() { + const l1Mixnode = { + mixId: 1, + owner: 'n1lftjhnl35cjsfd533zhgrwrspx6qmumd8vjgp9', + host: '80.85.86.75', + mixPort: 1789, + identityKey: '91mNjhJSBkJ9Lb6f1iuYMDQPLiX3kAv6paSUCWjGRwQz', + sphinxKey: 'DmfN1mL1T95nPXvLK44AQKCpW1pStHNQCi6Fgpz5dxDV', + layer: 1, + version: '1.1.20', + }; + const l2Mixnode = { + mixId: 2, + owner: 'n18ztkyh20gwzrel0e5m4sahd358fq9p4skwa7d3', + host: '139.162.199.75', + mixPort: 1789, + identityKey: 'BkLhuKQNyPS19sHZ3HHKCTKwK7hCU6XiFLndyZZHiB7s', + sphinxKey: '7KGC97tJRhJZKhDqFcsp4Vu715VVxizuD7BktnzuSmZC', + layer: 2, + version: '1.1.20', + }; + const l3Mixnode = { + mixId: 3, + owner: 'n1njq8h4nndp7ngays5el2rdp22hq67lwqcaq3ph', + host: '139.162.244.139', + identityKey: 'EPja9Kv8JtPHsFbzPdBQierMu5GmQy5roE5njyD6dmND', + sphinxKey: 'HWpsZChDrtEH8XNscW3qJMRzdCfUD8N8DmMcKqFv7tcf', + layer: 3, + }; + + const gateway = { + owner: 'n1d9lclqnfddgg57xe5p0fw4ng54m9f95hal5tlq', + host: '85.159.211.99', + mixPort: 1789, + clientsPort: 9000, + identityKey: '6pXQcG1Jt9hxBzMgTbQL5Y58z6mu4KXVRbA1idmibwsw', + sphinxKey: 'GSdqV7GFSwHWQrVV13pNLMeafTLDVFKBKVPxuhdGrpR3', + version: '1.1.19', + }; + + const mixnodes = new Map(); + mixnodes.set(1, [l1Mixnode]); + mixnodes.set(2, [l2Mixnode]); + mixnodes.set(3, [l3Mixnode]); + + const gateways = [gateway]; + + return { + mixnodes, gateways + } +} + + +function printAndDisplayTestResult(result) { + result.log_details(); + + self.postMessage({ + kind: 'DisplayTesterResults', + args: { + score: result.score(), + sentPackets: result.sent_packets, + receivedPackets: result.received_packets, + receivedAcks: result.received_acks, + duplicatePackets: result.duplicate_packets, + duplicateAcks: result.duplicate_acks, + }, + }); +} + +async function testWithTester() { + const preferredGateway = "6pXQcG1Jt9hxBzMgTbQL5Y58z6mu4KXVRbA1idmibwsw"; + const nymApi = 'https://qa-nym-api.qa.nymte.ch/api'; + + // A) construct with hardcoded topology + const topology = dummyTopology() + + // optional arguments: id, gateway + // mandatory (one of) arguments: topology, nymApi + const nodeTester = await new NymNodeTester({ id: "foomp", topology: topology }); + + // B) first get topology directly from nym-api + // const topology = await currentNetworkTopology(nymApi) + // const nodeTester = await new NymNodeTester({topology}); + + // C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers) + // const validator = 'https://qa-nym-api.qa.nymte.ch/api'; + // const nodeTester = await new NymNodeTester({nymApi}); + + self.onmessage = async event => { + if (event.data && event.data.kind) { + switch (event.data.kind) { + case 'MagicPayload': { + const {mixnodeIdentity} = event.data.args; + console.log("starting node test..."); + + let result = await nodeTester.test_node(mixnodeIdentity); + printAndDisplayTestResult(result) + } + } + } + }; +} + +async function main() { + console.log(">>>>>>>>>>>>>>>>>>>>> JS WORKER MAIN START"); + + // load rust WASM package + await wasm_bindgen(RUST_WASM_URL); + console.log('Loaded RUST WASM'); + + // sets up better stack traces in case of in-rust panics + set_panic_hook(); + // + // run test on simplified and dedicated tester: + await testWithTester(); + // + console.log(">>>>>>>>>>>>>>>>>>>>> JS WORKER MAIN END") +} + +// Let's get started! +main(); \ No newline at end of file diff --git a/wasm/node-tester/internal-dev/yarn-error.log b/wasm/node-tester/internal-dev/yarn-error.log new file mode 100644 index 0000000000..d3dea0efe1 --- /dev/null +++ b/wasm/node-tester/internal-dev/yarn-error.log @@ -0,0 +1,2261 @@ +Arguments: + /Users/jedrzej/.nvm/versions/node/v16.20.0/bin/node /Users/jedrzej/.nvm/versions/node/v16.20.0/bin/yarn install + +PATH: + /Users/jedrzej/.nvm/versions/node/v16.20.0/bin:/Library/Frameworks/Python.framework/Versions/3.11/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/Library/Apple/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Users/jedrzej/.cargo/bin:/Users/jedrzej/Library/Application Support/JetBrains/Toolbox/scripts + +Yarn version: + 1.22.19 + +Node version: + 16.20.0 + +Platform: + darwin arm64 + +Trace: + SyntaxError: /Users/jedrzej/workspace/nym/wasm/client/internal-dev/package.json: Unexpected token } in JSON at position 1030 + at JSON.parse () + at /Users/jedrzej/.nvm/versions/node/v16.20.0/lib/node_modules/yarn/lib/cli.js:1629:59 + at Generator.next () + at step (/Users/jedrzej/.nvm/versions/node/v16.20.0/lib/node_modules/yarn/lib/cli.js:310:30) + at /Users/jedrzej/.nvm/versions/node/v16.20.0/lib/node_modules/yarn/lib/cli.js:321:13 + +npm manifest: + { + "name": "create-wasm-app", + "version": "0.1.0", + "description": "create an app to consume rust-generated wasm packages", + "main": "index.js", + "bin": { + "create-wasm-app": ".bin/create-wasm-app.js" + }, + "scripts": { + "build": "webpack --config webpack.config.js", + "build:wasm": "cd ../ && make wasm-build", + "start": "webpack-dev-server --port 8001" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/rustwasm/create-wasm-app.git" + }, + "keywords": [ + "webassembly", + "wasm", + "rust", + "webpack" + ], + "author": "Dave Hrycyszyn ", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/nymtech/nym/issues" + }, + "homepage": "https://nymtech.net/docs", + "devDependencies": { + "copy-webpack-plugin": "^10.2.4", + "hello-wasm-pack": "^0.1.0", + "webpack": "^5.70.0", + "webpack-cli": "^4.9.2", + "webpack-dev-server": "^4.7.4" + }, + "dependencies": { + "@nymproject/nym-client-wasm": "file:../pkg", + } + } + +yarn manifest: + No manifest + +Lockfile: + # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. + # yarn lockfile v1 + + + "@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + + "@jridgewell/gen-mapping@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + + "@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + + "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + + "@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + + "@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + + "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + + "@leichtgewicht/ip-codec@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" + integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + + "@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + + "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + + "@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + + "@nymproject/nym-client-wasm@file:../pkg": + version "1.1.1" + + "@types/body-parser@*": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + + "@types/bonjour@^3.5.9": + version "3.5.10" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" + integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + dependencies: + "@types/node" "*" + + "@types/connect-history-api-fallback@^1.3.5": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" + integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + + "@types/connect@*": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" + + "@types/eslint-scope@^3.7.3": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + + "@types/eslint@*": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.37.0.tgz#29cebc6c2a3ac7fea7113207bf5a828fdf4d7ef1" + integrity sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + + "@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + + "@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + + "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": + version "4.17.33" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz#de35d30a9d637dc1450ad18dd583d75d5733d543" + integrity sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + + "@types/express@*", "@types/express@^4.17.13": + version "4.17.17" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4" + integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + + "@types/http-proxy@^1.17.8": + version "1.17.10" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.10.tgz#e576c8e4a0cc5c6a138819025a88e167ebb38d6c" + integrity sha512-Qs5aULi+zV1bwKAg5z1PWnDXWmsn+LxIvUGv6E2+OOMYhclZMO+OXd9pYVf2gLykf2I7IV2u7oTHwChPNsvJ7g== + dependencies: + "@types/node" "*" + + "@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + + "@types/mime@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" + integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== + + "@types/node@*": + version "18.15.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" + integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q== + + "@types/qs@*": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + + "@types/range-parser@*": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + + "@types/retry@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" + integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== + + "@types/serve-index@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" + integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + dependencies: + "@types/express" "*" + + "@types/serve-static@*", "@types/serve-static@^1.13.10": + version "1.15.1" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.1.tgz#86b1753f0be4f9a1bee68d459fcda5be4ea52b5d" + integrity sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ== + dependencies: + "@types/mime" "*" + "@types/node" "*" + + "@types/sockjs@^0.3.33": + version "0.3.33" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" + integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + dependencies: + "@types/node" "*" + + "@types/ws@^8.5.1": + version "8.5.4" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5" + integrity sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg== + dependencies: + "@types/node" "*" + + "@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + + "@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + + "@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + + "@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + + "@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + + "@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + + "@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + + "@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + + "@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + + "@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + + "@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + + "@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + + "@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + + "@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + + "@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@xtuc/long" "4.2.2" + + "@webpack-cli/configtest@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" + integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== + + "@webpack-cli/info@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" + integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== + dependencies: + envinfo "^7.7.3" + + "@webpack-cli/serve@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" + integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== + + "@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + + "@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + + accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + + acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + + acorn@^8.5.0, acorn@^8.7.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + + ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + + ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + + ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + + ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + + ajv@^8.0.0, ajv@^8.8.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + + ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + + anymatch@~3.1.2: + 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" + + array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + + array-flatten@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + + array-union@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" + integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== + + 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== + + batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== + + binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + + body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + + bonjour-service@^1.0.11: + version "1.1.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.1.1.tgz#960948fa0e0153f5d26743ab15baf8e33752c135" + integrity sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg== + dependencies: + array-flatten "^2.1.2" + dns-equal "^1.0.0" + fast-deep-equal "^3.1.3" + multicast-dns "^7.2.5" + + 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" + + braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + + browserslist@^4.14.5: + version "4.21.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" + integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== + dependencies: + caniuse-lite "^1.0.30001449" + electron-to-chromium "^1.4.284" + node-releases "^2.0.8" + update-browserslist-db "^1.0.10" + + 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== + + bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + + bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + + call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + + caniuse-lite@^1.0.30001449: + version "1.0.30001474" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001474.tgz#13b6fe301a831fe666cce8ca4ef89352334133d5" + integrity sha512-iaIZ8gVrWfemh5DG3T9/YqarVZoYf0r188IjaGwx68j4Pf0SGY6CQkmJUIE+NZHkkecQGohzXmBGEwWDr9aM3Q== + + chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + + chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + + clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + + colorette@^2.0.10, colorette@^2.0.14: + version "2.0.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + + commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + + commander@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + + compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + + compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + + 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== + + connect-history-api-fallback@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" + integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== + + content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + + content-type@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + + cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + + cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + + copy-webpack-plugin@^10.2.4: + version "10.2.4" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe" + integrity sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg== + dependencies: + fast-glob "^3.2.7" + glob-parent "^6.0.1" + globby "^12.0.2" + normalize-path "^3.0.0" + schema-utils "^4.0.0" + serialize-javascript "^6.0.0" + + core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + + 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" + + debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + + debug@^4.1.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + + default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== + dependencies: + execa "^5.0.0" + + define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + + depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + + depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + + destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + + detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + + dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + + dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== + + dns-packet@^5.2.2: + version "5.5.0" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.5.0.tgz#f59cbf3396c130957c56a6ad5fd3959ccdc30065" + integrity sha512-USawdAUzRkV6xrqTjiAEp6M9YagZEzWcSUaZTcIFAiyQWW1SoI6KyId8y2+/71wbgHKQAKd+iupLv4YvEwYWvA== + dependencies: + "@leichtgewicht/ip-codec" "^2.0.1" + + ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + + electron-to-chromium@^1.4.284: + version "1.4.352" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.352.tgz#be96bd7c2f4b980deebc9338a49a67430a33ed73" + integrity sha512-ikFUEyu5/q+wJpMOxWxTaEVk2M1qKqTGKKyfJmod1CPZxKfYnxVS41/GCBQg21ItBpZybyN8sNpRqCUGm+Zc4Q== + + encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + + enhanced-resolve@^5.10.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" + integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + + envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + + es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + + escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + + escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + + eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + + esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + + estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + + estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + + etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + + eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + + events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + + 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" + + express@^4.17.3: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + + fast-glob@^3.2.7: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + + fast-json-stable-stringify@^2.0.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== + + fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + + fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + + faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + + fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + + finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + + find-up@^4.0.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" + + follow-redirects@^1.0.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + + forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + + fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + + fs-monkey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" + integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== + + 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.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + + function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + + get-intrinsic@^1.0.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + + 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-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + + glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + + glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + + glob@^7.1.3: + 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" + + globby@^12.0.2: + version "12.2.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" + integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== + dependencies: + array-union "^3.0.1" + dir-glob "^3.0.1" + fast-glob "^3.2.7" + ignore "^5.1.9" + merge2 "^1.4.1" + slash "^4.0.0" + + "go-mix-conn@file:../go-mix-conn/build": + version "0.0.0" + + graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6, 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== + + handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== + + 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-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== + + has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + + hello-wasm-pack@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/hello-wasm-pack/-/hello-wasm-pack-0.1.0.tgz#482a2e3371828056ac35f5b5fec76c0b99dcd530" + integrity sha512-3hx0GDkDLf/a9ThCMV2qG4mwza8N/MCtm8aeFFc/cdBCL2zMJ1kW1wjNl7xPqD1lz8Yl5+uhnc/cpui4dLwz/w== + + hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + + html-entities@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" + integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== + + http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== + + http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + + http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + + http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + + http-proxy-middleware@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" + integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + dependencies: + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" + + http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + + 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== + + iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + + ignore@^5.1.9: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + + import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + + 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, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + + inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + + interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + + ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + + ipaddr.js@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" + integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== + + is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + + is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + + is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + + is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + + is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + + 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-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + + is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + + 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== + + is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + + isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + + isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + + isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + + jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + + json-parse-even-better-errors@^2.3.1: + 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-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + + json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + + kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + + launch-editor@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.0.tgz#4c0c1a6ac126c572bd9ff9a30da1d2cae66defd7" + integrity sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ== + dependencies: + picocolors "^1.0.0" + shell-quote "^1.7.3" + + loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + + 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" + + media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + + memfs@^3.4.3: + version "3.4.13" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.13.tgz#248a8bd239b3c240175cd5ec548de5227fc4f345" + integrity sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg== + dependencies: + fs-monkey "^1.0.3" + + merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + + 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== + + merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + + 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.2, micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + + mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + 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.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + 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@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + + 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== + + minimalistic-assert@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + + minimatch@^3.1.1: + 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" + + ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + + 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== + + ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + + multicast-dns@^7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" + integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== + dependencies: + dns-packet "^5.2.2" + thunky "^1.0.2" + + negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + + neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + + node-forge@^1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + + node-releases@^2.0.8: + version "2.0.10" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" + integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== + + normalize-path@^3.0.0, 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.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + + obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + + on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + + on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + + once@^1.3.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" + + open@^8.0.9: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.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-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-retry@^4.5.0: + version "4.6.2" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" + integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== + dependencies: + "@types/retry" "0.12.0" + retry "^0.13.1" + + 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== + + parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + + 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== + + path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + + path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + + picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + + 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" + + process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + + proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + + punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + + qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + + queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + + randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + + range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + + raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + + readable-stream@^2.0.1: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + + readable-stream@^3.0.6: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + + readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + + rechoir@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" + integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== + dependencies: + resolve "^1.9.0" + + require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + + requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + + 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@^1.9.0: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + + retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + + reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + + rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + + run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + + safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + + "safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + + schema-utils@^3.1.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + + schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + + select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== + + selfsigned@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" + integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== + dependencies: + node-forge "^1" + + send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + + serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" + integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== + dependencies: + randombytes "^2.1.0" + + serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + + serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + + setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + + setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + + shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.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== + + shell-quote@^1.7.3: + version "1.8.0" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.0.tgz#20d078d0eaf71d54f43bd2ba14a1b5b9bfa5c8ba" + integrity sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ== + + side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + + signal-exit@^3.0.3: + 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== + + slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + + sockjs@^0.3.24: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + + source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + + source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + + spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + + spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + + statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + + "statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + + string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + + string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + + 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== + + 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== + + tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + + terser-webpack-plugin@^5.1.3: + version "5.3.7" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz#ef760632d24991760f339fe9290deb936ad1ffc7" + integrity sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.17" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.16.5" + + terser@^5.16.5: + version "5.16.8" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.8.tgz#ccde583dabe71df3f4ed02b65eb6532e0fae15d5" + integrity sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA== + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + commander "^2.20.0" + source-map-support "~0.5.20" + + thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + + 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" + + toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + + type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + + unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + + update-browserslist-db@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + + uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + + util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + + utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + + uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + + vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + + watchpack@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + + wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + + webpack-cli@^4.9.2: + version "4.10.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" + integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.2.0" + "@webpack-cli/info" "^1.5.0" + "@webpack-cli/serve" "^1.7.0" + colorette "^2.0.14" + commander "^7.0.0" + cross-spawn "^7.0.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + webpack-merge "^5.7.3" + + webpack-dev-middleware@^5.3.1: + version "5.3.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" + integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== + dependencies: + colorette "^2.0.10" + memfs "^3.4.3" + mime-types "^2.1.31" + range-parser "^1.2.1" + schema-utils "^4.0.0" + + webpack-dev-server@^4.7.4: + version "4.13.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.13.2.tgz#d97445481d78691efe6d9a3b230833d802fc31f9" + integrity sha512-5i6TrGBRxG4vnfDpB6qSQGfnB6skGBXNL5/542w2uRGLimX6qeE5BQMLrzIC3JYV/xlGOv+s+hTleI9AZKUQNw== + dependencies: + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/express" "^4.17.13" + "@types/serve-index" "^1.9.1" + "@types/serve-static" "^1.13.10" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.5.1" + ansi-html-community "^0.0.8" + bonjour-service "^1.0.11" + chokidar "^3.5.3" + colorette "^2.0.10" + compression "^1.7.4" + connect-history-api-fallback "^2.0.0" + default-gateway "^6.0.3" + express "^4.17.3" + graceful-fs "^4.2.6" + html-entities "^2.3.2" + http-proxy-middleware "^2.0.3" + ipaddr.js "^2.0.1" + launch-editor "^2.6.0" + open "^8.0.9" + p-retry "^4.5.0" + rimraf "^3.0.2" + schema-utils "^4.0.0" + selfsigned "^2.1.1" + serve-index "^1.9.1" + sockjs "^0.3.24" + spdy "^4.0.2" + webpack-dev-middleware "^5.3.1" + ws "^8.13.0" + + webpack-merge@^5.7.3: + version "5.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + + webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + + webpack@^5.70.0: + version "5.77.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.77.0.tgz#dea3ad16d7ea6b84aa55fa42f4eac9f30e7eb9b4" + integrity sha512-sbGNjBr5Ya5ss91yzjeJTLKyfiwo5C628AFjEa6WSXcZa4E+F57om3Cc8xLb1Jh0b243AWuSYRf3dn7HVeFQ9Q== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.7.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.10.0" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.4.0" + webpack-sources "^3.2.3" + + websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + + websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + + 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" + + wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + + 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== + + ws@^8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== diff --git a/wasm/node-tester/internal-dev/yarn.lock b/wasm/node-tester/internal-dev/yarn.lock new file mode 100644 index 0000000000..df787a4a65 --- /dev/null +++ b/wasm/node-tester/internal-dev/yarn.lock @@ -0,0 +1,2189 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + +"@jridgewell/gen-mapping@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@leichtgewicht/ip-codec@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" + integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nymproject/nym_node_tester_wasm@file:../../../dist/wasm/node-tester": + version "1.0.0" + +"@types/body-parser@*": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/bonjour@^3.5.9": + version "3.5.10" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" + integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + dependencies: + "@types/node" "*" + +"@types/connect-history-api-fallback@^1.3.5": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" + integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" + +"@types/eslint-scope@^3.7.3": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.37.0.tgz#29cebc6c2a3ac7fea7113207bf5a828fdf4d7ef1" + integrity sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + +"@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": + version "4.17.33" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz#de35d30a9d637dc1450ad18dd583d75d5733d543" + integrity sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@*", "@types/express@^4.17.13": + version "4.17.17" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4" + integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/http-proxy@^1.17.8": + version "1.17.10" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.10.tgz#e576c8e4a0cc5c6a138819025a88e167ebb38d6c" + integrity sha512-Qs5aULi+zV1bwKAg5z1PWnDXWmsn+LxIvUGv6E2+OOMYhclZMO+OXd9pYVf2gLykf2I7IV2u7oTHwChPNsvJ7g== + dependencies: + "@types/node" "*" + +"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/mime@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" + integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== + +"@types/node@*": + version "18.15.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" + integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q== + +"@types/qs@*": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/range-parser@*": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + +"@types/retry@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" + integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== + +"@types/serve-index@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" + integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + dependencies: + "@types/express" "*" + +"@types/serve-static@*", "@types/serve-static@^1.13.10": + version "1.15.1" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.1.tgz#86b1753f0be4f9a1bee68d459fcda5be4ea52b5d" + integrity sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ== + dependencies: + "@types/mime" "*" + "@types/node" "*" + +"@types/sockjs@^0.3.33": + version "0.3.33" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" + integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + dependencies: + "@types/node" "*" + +"@types/ws@^8.5.1": + version "8.5.4" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5" + integrity sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg== + dependencies: + "@types/node" "*" + +"@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + +"@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + +"@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + +"@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + +"@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + +"@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + +"@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + +"@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + +"@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + +"@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" + integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== + +"@webpack-cli/info@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" + integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" + integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + +acorn@^8.5.0, acorn@^8.7.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.0, ajv@^8.8.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + +anymatch@~3.1.2: + 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" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +array-flatten@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + +array-union@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" + integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== + +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== + +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +bonjour-service@^1.0.11: + version "1.1.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.1.1.tgz#960948fa0e0153f5d26743ab15baf8e33752c135" + integrity sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg== + dependencies: + array-flatten "^2.1.2" + dns-equal "^1.0.0" + fast-deep-equal "^3.1.3" + multicast-dns "^7.2.5" + +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" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.14.5: + version "4.21.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" + integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== + dependencies: + caniuse-lite "^1.0.30001449" + electron-to-chromium "^1.4.284" + node-releases "^2.0.8" + update-browserslist-db "^1.0.10" + +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== + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +caniuse-lite@^1.0.30001449: + version "1.0.30001474" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001474.tgz#13b6fe301a831fe666cce8ca4ef89352334133d5" + integrity sha512-iaIZ8gVrWfemh5DG3T9/YqarVZoYf0r188IjaGwx68j4Pf0SGY6CQkmJUIE+NZHkkecQGohzXmBGEwWDr9aM3Q== + +chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +colorette@^2.0.10, colorette@^2.0.14: + version "2.0.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +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== + +connect-history-api-fallback@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" + integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +copy-webpack-plugin@^10.2.4: + version "10.2.4" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe" + integrity sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg== + dependencies: + fast-glob "^3.2.7" + glob-parent "^6.0.1" + globby "^12.0.2" + normalize-path "^3.0.0" + schema-utils "^4.0.0" + serialize-javascript "^6.0.0" + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +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" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^4.1.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== + dependencies: + execa "^5.0.0" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== + +dns-packet@^5.2.2: + version "5.5.0" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.5.0.tgz#f59cbf3396c130957c56a6ad5fd3959ccdc30065" + integrity sha512-USawdAUzRkV6xrqTjiAEp6M9YagZEzWcSUaZTcIFAiyQWW1SoI6KyId8y2+/71wbgHKQAKd+iupLv4YvEwYWvA== + dependencies: + "@leichtgewicht/ip-codec" "^2.0.1" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.284: + version "1.4.352" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.352.tgz#be96bd7c2f4b980deebc9338a49a67430a33ed73" + integrity sha512-ikFUEyu5/q+wJpMOxWxTaEVk2M1qKqTGKKyfJmod1CPZxKfYnxVS41/GCBQg21ItBpZybyN8sNpRqCUGm+Zc4Q== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +enhanced-resolve@^5.10.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" + integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +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" + +express@^4.17.3: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.7: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.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== + +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-up@^4.0.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" + +follow-redirects@^1.0.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-monkey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" + integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== + +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.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-intrinsic@^1.0.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +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-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@^7.1.3: + 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" + +globby@^12.0.2: + version "12.2.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" + integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== + dependencies: + array-union "^3.0.1" + dir-glob "^3.0.1" + fast-glob "^3.2.7" + ignore "^5.1.9" + merge2 "^1.4.1" + slash "^4.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6, 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== + +handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== + +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-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== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hello-wasm-pack@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/hello-wasm-pack/-/hello-wasm-pack-0.1.0.tgz#482a2e3371828056ac35f5b5fec76c0b99dcd530" + integrity sha512-3hx0GDkDLf/a9ThCMV2qG4mwza8N/MCtm8aeFFc/cdBCL2zMJ1kW1wjNl7xPqD1lz8Yl5+uhnc/cpui4dLwz/w== + +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + +html-entities@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" + integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== + +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + +http-proxy-middleware@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" + integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + dependencies: + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" + +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +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== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore@^5.1.9: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +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, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + +interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +ipaddr.js@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" + integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +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-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +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== + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +json-parse-even-better-errors@^2.3.1: + 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-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +launch-editor@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.0.tgz#4c0c1a6ac126c572bd9ff9a30da1d2cae66defd7" + integrity sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ== + dependencies: + picocolors "^1.0.0" + shell-quote "^1.7.3" + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +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" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +memfs@^3.4.3: + version "3.4.13" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.13.tgz#248a8bd239b3c240175cd5ec548de5227fc4f345" + integrity sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg== + dependencies: + fs-monkey "^1.0.3" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +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== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +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.2, micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + 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.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + 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@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +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== + +minimalistic-assert@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimatch@^3.1.1: + 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" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +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== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multicast-dns@^7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" + integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== + dependencies: + dns-packet "^5.2.2" + thunky "^1.0.2" + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-forge@^1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + +node-releases@^2.0.8: + version "2.0.10" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" + integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== + +normalize-path@^3.0.0, 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.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.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" + +open@^8.0.9: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.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-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-retry@^4.5.0: + version "4.6.2" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" + integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== + dependencies: + "@types/retry" "0.12.0" + retry "^0.13.1" + +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== + +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +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== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +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" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +readable-stream@^2.0.1: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +rechoir@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" + integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== + dependencies: + resolve "^1.9.0" + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +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@^1.9.0: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +schema-utils@^3.1.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== + +selfsigned@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" + integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== + dependencies: + node-forge "^1" + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" + integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== + dependencies: + randombytes "^2.1.0" + +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.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== + +shell-quote@^1.7.3: + version "1.8.0" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.0.tgz#20d078d0eaf71d54f43bd2ba14a1b5b9bfa5c8ba" + integrity sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.3: + 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== + +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + +sockjs@^0.3.24: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +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== + +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== + +tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +terser-webpack-plugin@^5.1.3: + version "5.3.7" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz#ef760632d24991760f339fe9290deb936ad1ffc7" + integrity sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.17" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.16.5" + +terser@^5.16.5: + version "5.16.8" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.8.tgz#ccde583dabe71df3f4ed02b65eb6532e0fae15d5" + integrity sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA== + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + commander "^2.20.0" + source-map-support "~0.5.20" + +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + +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" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +update-browserslist-db@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +watchpack@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + +webpack-cli@^4.9.2: + version "4.10.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" + integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.2.0" + "@webpack-cli/info" "^1.5.0" + "@webpack-cli/serve" "^1.7.0" + colorette "^2.0.14" + commander "^7.0.0" + cross-spawn "^7.0.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + webpack-merge "^5.7.3" + +webpack-dev-middleware@^5.3.1: + version "5.3.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" + integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== + dependencies: + colorette "^2.0.10" + memfs "^3.4.3" + mime-types "^2.1.31" + range-parser "^1.2.1" + schema-utils "^4.0.0" + +webpack-dev-server@^4.7.4: + version "4.13.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.13.2.tgz#d97445481d78691efe6d9a3b230833d802fc31f9" + integrity sha512-5i6TrGBRxG4vnfDpB6qSQGfnB6skGBXNL5/542w2uRGLimX6qeE5BQMLrzIC3JYV/xlGOv+s+hTleI9AZKUQNw== + dependencies: + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/express" "^4.17.13" + "@types/serve-index" "^1.9.1" + "@types/serve-static" "^1.13.10" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.5.1" + ansi-html-community "^0.0.8" + bonjour-service "^1.0.11" + chokidar "^3.5.3" + colorette "^2.0.10" + compression "^1.7.4" + connect-history-api-fallback "^2.0.0" + default-gateway "^6.0.3" + express "^4.17.3" + graceful-fs "^4.2.6" + html-entities "^2.3.2" + http-proxy-middleware "^2.0.3" + ipaddr.js "^2.0.1" + launch-editor "^2.6.0" + open "^8.0.9" + p-retry "^4.5.0" + rimraf "^3.0.2" + schema-utils "^4.0.0" + selfsigned "^2.1.1" + serve-index "^1.9.1" + sockjs "^0.3.24" + spdy "^4.0.2" + webpack-dev-middleware "^5.3.1" + ws "^8.13.0" + +webpack-merge@^5.7.3: + version "5.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@^5.70.0: + version "5.77.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.77.0.tgz#dea3ad16d7ea6b84aa55fa42f4eac9f30e7eb9b4" + integrity sha512-sbGNjBr5Ya5ss91yzjeJTLKyfiwo5C628AFjEa6WSXcZa4E+F57om3Cc8xLb1Jh0b243AWuSYRf3dn7HVeFQ9Q== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.7.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.10.0" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.4.0" + webpack-sources "^3.2.3" + +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +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" + +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + +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== + +ws@^8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== diff --git a/clients/webassembly/src/tester/ephemeral_receiver.rs b/wasm/node-tester/src/ephemeral_receiver.rs similarity index 96% rename from clients/webassembly/src/tester/ephemeral_receiver.rs rename to wasm/node-tester/src/ephemeral_receiver.rs index 2d3117addd..a7a9545de6 100644 --- a/clients/webassembly/src/tester/ephemeral_receiver.rs +++ b/wasm/node-tester/src/ephemeral_receiver.rs @@ -1,11 +1,11 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::tester::helpers::{NodeTestResult, WasmTestMessageExt}; +use crate::types::{NodeTestResult, WasmTestMessageExt}; use futures::StreamExt; use nym_node_tester_utils::processor::Received; use nym_node_tester_utils::receiver::ReceivedReceiver; -use nym_sphinx::chunking::fragment::FragmentIdentifier; +use nym_node_tester_utils::FragmentIdentifier; use std::collections::HashSet; use std::time::Duration; use tokio::sync::MutexGuard as AsyncMutexGuard; diff --git a/wasm/node-tester/src/error.rs b/wasm/node-tester/src/error.rs new file mode 100644 index 0000000000..41004c755c --- /dev/null +++ b/wasm/node-tester/src/error.rs @@ -0,0 +1,64 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use js_sys::Promise; +use nym_node_tester_utils::error::NetworkTestingError; +use thiserror::Error; +use wasm_client_core::error::WasmCoreError; +use wasm_client_core::topology::WasmTopologyError; +use wasm_client_core::{ClientCoreError, GatewayClientError}; +use wasm_utils::wasm_error; + +#[derive(Debug, Error)] +pub enum NodeTesterError { + #[error( + "A node test is already in progress. Wait for it to finish before starting another one." + )] + TestInProgress, + + #[error( + "both nymApi address and explicit topology were specified - please use only one of them" + )] + DuplicateTopologySource, + + #[error("neither nymApi address or explicit topology were specified")] + NoTopologySource, + + #[error("could not parse provided tester arguments: {err}")] + MalformedNodeTesterArguments { err: String }, + + #[error(transparent)] + CoreError { + #[from] + source: WasmCoreError, + }, + + #[error("provided topology was malformed: {source}")] + InvalidTopology { + #[from] + source: WasmTopologyError, + }, + + #[error("failed to test the node: {source}")] + NodeTestingFailure { + #[from] + source: NetworkTestingError, + }, + + #[error("experienced an error with the gateway connection: {source}")] + GatewayConnectionError { + #[from] + source: GatewayClientError, + }, +} + +// I dislike this so much - there must be a better way. +impl From for NodeTesterError { + fn from(value: ClientCoreError) -> Self { + NodeTesterError::CoreError { + source: WasmCoreError::BaseClientError { source: value }, + } + } +} + +wasm_error!(NodeTesterError); diff --git a/clients/webassembly/src/tester/helpers.rs b/wasm/node-tester/src/helpers.rs similarity index 62% rename from clients/webassembly/src/tester/helpers.rs rename to wasm/node-tester/src/helpers.rs index b2ce1b9e5c..fa7790e2f6 100644 --- a/clients/webassembly/src/tester/helpers.rs +++ b/wasm/node-tester/src/helpers.rs @@ -4,19 +4,18 @@ // due to expansion of #[wasm_bindgen] macro on NodeTestResult #![allow(clippy::drop_non_drop)] -use crate::error::WasmClientError; +use crate::error::NodeTesterError; use crate::tester::LockedGatewayClient; +use crate::types::WasmTestMessageExt; use js_sys::Promise; use nym_node_tester_utils::processor::Received; use nym_node_tester_utils::receiver::ReceivedReceiver; -use serde::{Deserialize, Serialize}; -use std::fmt::{Display, Formatter}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use tokio::sync::{Mutex as AsyncMutex, MutexGuard as AsyncMutexGuard}; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; -use wasm_utils::{console_log, console_warn}; +use wasm_utils::console_warn; #[derive(Clone)] pub(super) struct ReceivedReceiverWrapper(Arc>>); @@ -46,55 +45,6 @@ impl ReceivedReceiverWrapper { } } -#[derive(Serialize, Deserialize, Copy, Clone)] -pub struct WasmTestMessageExt { - pub test_id: u32, -} - -impl WasmTestMessageExt { - pub fn new(test_id: u32) -> Self { - WasmTestMessageExt { test_id } - } -} - -// TODO: maybe put it in the tester utils -#[wasm_bindgen] -pub struct NodeTestResult { - pub sent_packets: u32, - pub received_packets: u32, - pub received_acks: u32, - - pub duplicate_packets: u32, - pub duplicate_acks: u32, -} - -impl Display for NodeTestResult { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - writeln!(f, "Test results: ")?; - writeln!(f, "Total score: {:.2}%", self.score())?; - writeln!(f, "Sent packets: {}", self.sent_packets)?; - writeln!(f, "Received (valid) packets: {}", self.received_packets)?; - writeln!(f, "Received (valid) acks: {}", self.received_acks)?; - writeln!(f, "Received duplicate packets: {}", self.duplicate_packets)?; - write!(f, "Received duplicate acks: {}", self.duplicate_acks) - } -} - -#[wasm_bindgen] -impl NodeTestResult { - pub fn log_details(&self) { - console_log!("{}", self) - } - - pub fn score(&self) -> f32 { - let expected = self.sent_packets * 2; - let actual = (self.received_packets + self.received_acks) - .saturating_sub(self.duplicate_packets + self.duplicate_acks); - - actual as f32 / expected as f32 * 100. - } -} - pub(crate) struct TestMarker { value: Arc, } @@ -127,7 +77,7 @@ impl GatewayReconnection for LockedGatewayClient { guard .disconnect() .await - .map_err(|err| JsValue::from(WasmClientError::from(err)))?; + .map_err(|err| JsValue::from(NodeTesterError::from(err)))?; Ok(JsValue::undefined()) }) } @@ -140,7 +90,7 @@ impl GatewayReconnection for LockedGatewayClient { guard .try_reconnect() .await - .map_err(|err| JsValue::from(WasmClientError::from(err)))?; + .map_err(|err| JsValue::from(NodeTesterError::from(err)))?; Ok(JsValue::undefined()) }) } diff --git a/wasm/node-tester/src/lib.rs b/wasm/node-tester/src/lib.rs new file mode 100644 index 0000000000..f2cdee034d --- /dev/null +++ b/wasm/node-tester/src/lib.rs @@ -0,0 +1,16 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +#[cfg(target_arch = "wasm32")] +mod ephemeral_receiver; +#[cfg(target_arch = "wasm32")] +pub mod error; +#[cfg(target_arch = "wasm32")] +mod helpers; +#[cfg(target_arch = "wasm32")] +pub mod tester; +#[cfg(target_arch = "wasm32")] +pub mod types; + +#[cfg(target_arch = "wasm32")] +pub use wasm_client_core::set_panic_hook; diff --git a/clients/webassembly/src/tester/mod.rs b/wasm/node-tester/src/tester.rs similarity index 72% rename from clients/webassembly/src/tester/mod.rs rename to wasm/node-tester/src/tester.rs index ba70062f3b..5a5d7f5f34 100644 --- a/clients/webassembly/src/tester/mod.rs +++ b/wasm/node-tester/src/tester.rs @@ -1,52 +1,46 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::constants::NODE_TESTER_ID; -use crate::error::WasmClientError; -use crate::helpers::{current_network_topology_async, setup_from_topology}; -use crate::storage::ClientStorage; -use crate::tester::ephemeral_receiver::EphemeralTestReceiver; -use crate::tester::helpers::{ - GatewayReconnection, NodeTestResult, ReceivedReceiverWrapper, TestMarker, WasmTestMessageExt, -}; -use crate::topology::WasmNymTopology; +use crate::ephemeral_receiver::EphemeralTestReceiver; +use crate::error::NodeTesterError; +use crate::helpers::{GatewayReconnection, ReceivedReceiverWrapper, TestMarker}; +use crate::types::{NodeTestResult, WasmTestMessageExt}; use futures::channel::mpsc; use js_sys::Promise; -use nym_bandwidth_controller::BandwidthController; -use nym_client_core::client::key_manager::ManagedKeys; -use nym_client_core::init::{InitialisationDetails, InitialisationResult}; -use nym_credential_storage::ephemeral_storage::EphemeralStorage; -use nym_gateway_client::GatewayClient; use nym_node_tester_utils::receiver::SimpleMessageReceiver; -use nym_node_tester_utils::{NodeTester, TestMessage}; -use nym_sphinx::addressing::clients::Recipient; -use nym_sphinx::addressing::nodes::NodeIdentity; -use nym_sphinx::params::PacketSize; -use nym_sphinx::preparer::PreparedFragment; +use nym_node_tester_utils::{NodeTester, PacketSize, PreparedFragment}; use nym_task::TaskManager; -use nym_topology::NymTopology; -use nym_validator_client::client::IdentityKey; -use nym_validator_client::QueryReqwestRpcNyxdClient; use rand::rngs::OsRng; +use serde::{Deserialize, Serialize}; use std::collections::HashSet; use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; use std::sync::{Arc, Mutex as SyncMutex}; use std::time::Duration; use tokio::sync::Mutex as AsyncMutex; +use tsify::Tsify; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; -use wasm_utils::{check_promise_result, console_log, PromisableResult}; +use wasm_client_core::helpers::{ + current_network_topology_async, setup_from_topology, EphemeralCredentialStorage, +}; +use wasm_client_core::storage::ClientStorage; +use wasm_client_core::topology::WasmNymTopology; +use wasm_client_core::{ + nym_task, BandwidthController, GatewayClient, IdentityKey, InitialisationDetails, + InitialisationResult, ManagedKeys, NodeIdentity, NymTopology, QueryReqwestRpcNyxdClient, + Recipient, +}; +use wasm_utils::check_promise_result; +use wasm_utils::error::PromisableResult; -mod ephemeral_receiver; -pub(crate) mod helpers; - -pub type NodeTestMessage = TestMessage; -type LockedGatewayClient = - Arc>>; +pub const NODE_TESTER_ID: &str = "_nym-node-tester"; pub(crate) const DEFAULT_TEST_TIMEOUT: Duration = Duration::from_secs(10); pub(crate) const DEFAULT_TEST_PACKETS: u32 = 20; +pub(crate) type LockedGatewayClient = + Arc>>; + #[wasm_bindgen] pub struct NymNodeTester { test_in_progress: Arc, @@ -78,7 +72,8 @@ pub struct NymNodeTesterBuilder { base_topology: NymTopology, // unimplemented - bandwidth_controller: Option>, + bandwidth_controller: + Option>, } fn address(keys: &ManagedKeys, gateway_identity: NodeIdentity) -> Recipient { @@ -89,55 +84,69 @@ fn address(keys: &ManagedKeys, gateway_identity: NodeIdentity) -> Recipient { ) } +#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +pub struct NymNodeTesterOpts { + #[tsify(optional)] + id: Option, + + #[tsify(optional)] + nym_api: Option, + + #[tsify(optional)] + topology: Option, + + #[tsify(optional)] + gateway: Option, +} + #[wasm_bindgen] impl NymNodeTesterBuilder { #[wasm_bindgen(constructor)] - pub fn new( - base_topology: WasmNymTopology, - id: Option, - gateway: Option, - ) -> NymNodeTesterBuilder { - NymNodeTesterBuilder { - id, - gateway, - base_topology: base_topology.into(), - bandwidth_controller: None, + #[allow(clippy::new_ret_no_self)] + pub fn new(args: NymNodeTesterOpts) -> Promise { + future_to_promise(async move { Self::new_async(args).await.into_promise_result() }) + } + + async fn new_async(args: NymNodeTesterOpts) -> Result { + if args.nym_api.is_some() && args.topology.is_some() { + return Err(NodeTesterError::DuplicateTopologySource); + } + if args.nym_api.is_none() && args.topology.is_none() { + return Err(NodeTesterError::NoTopologySource); } - } - async fn _new_with_api( - api_url: String, - id: Option, - gateway: Option, - ) -> Result { - let topology = current_network_topology_async(api_url).await?; - Ok(NymNodeTesterBuilder::new(topology, id, gateway)) - } + let topology = if let Some(topology) = args.topology { + topology + } else { + // the unwrap here is fine as we just ensured one of the branches would be true + current_network_topology_async(args.nym_api.unwrap()).await? + }; - pub fn new_with_api( - api_url: String, - id: Option, - gateway: Option, - ) -> Promise { - future_to_promise(async move { - Self::_new_with_api(api_url, id, gateway) - .await - .into_promise_result() + Ok(NymNodeTesterBuilder { + gateway: args.gateway, + id: args.id, + base_topology: topology.try_into()?, + bandwidth_controller: None, }) } async fn gateway_info( &self, client_store: &ClientStorage, - ) -> Result { + ) -> Result { if let Ok(loaded) = InitialisationDetails::try_load(client_store, client_store).await { Ok(loaded.into()) } else { - setup_from_topology(self.gateway.clone(), &self.base_topology, client_store).await + Ok( + setup_from_topology(self.gateway.clone(), &self.base_topology, client_store) + .await?, + ) } } - async fn _setup_client(mut self) -> Result { + async fn _setup_client(mut self) -> Result { let task_manager = TaskManager::default(); let storage_id = if let Some(client_id) = &self.id { @@ -227,7 +236,7 @@ async fn test_mixnode( processed_receiver: ReceivedReceiverWrapper, _test_marker: TestMarker, timeout: Duration, -) -> Result { +) -> Result { let num_test_packets = test_packets.len() as u32; let expected_ack_ids = test_packets @@ -258,38 +267,17 @@ async fn test_mixnode( impl NymNodeTester { #[wasm_bindgen(constructor)] #[allow(clippy::new_ret_no_self)] - pub fn new( - topology: WasmNymTopology, - id: Option, - gateway: Option, - ) -> Promise { - console_log!("constructing node tester!"); - NymNodeTesterBuilder::new(topology, id, gateway).setup_client() + pub fn new(args: NymNodeTesterOpts) -> Promise { + future_to_promise(async move { Self::new_async(args).await.into_promise_result() }) } - async fn _new_with_api( - api_url: String, - id: Option, - gateway: Option, - ) -> Result { - NymNodeTesterBuilder::_new_with_api(api_url, id, gateway) + async fn new_async(args: NymNodeTesterOpts) -> Result { + NymNodeTesterBuilder::new_async(args) .await? ._setup_client() .await } - pub fn new_with_api( - api_url: String, - id: Option, - gateway: Option, - ) -> Promise { - future_to_promise(async move { - Self::_new_with_api(api_url, id, gateway) - .await - .into_promise_result() - }) - } - pub fn disconnect_from_gateway(&self) -> Promise { self.gateway_client.disconnect_from_gateway() } @@ -303,7 +291,7 @@ impl NymNodeTester { mixnode_identity: String, test_nonce: u32, num_test_packets: u32, - ) -> Result, WasmClientError> { + ) -> Result, NodeTesterError> { let test_ext = WasmTestMessageExt::new(test_nonce); let mut tester_permit = self.tester.lock().expect("mutex got poisoned"); tester_permit @@ -330,7 +318,7 @@ impl NymNodeTester { // mark start of the test if self.test_in_progress.swap(true, Ordering::SeqCst) { - return WasmClientError::TestInProgress.into_rejected_promise(); + return NodeTesterError::TestInProgress.into_rejected_promise(); } // prepare test packets diff --git a/wasm/node-tester/src/types.rs b/wasm/node-tester/src/types.rs new file mode 100644 index 0000000000..e1a5dcf766 --- /dev/null +++ b/wasm/node-tester/src/types.rs @@ -0,0 +1,59 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use nym_node_tester_utils::TestMessage; +use serde::{Deserialize, Serialize}; +use std::fmt::{Display, Formatter}; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_utils::console_log; + +pub type NodeTestMessage = TestMessage; + +#[derive(Serialize, Deserialize, Copy, Clone)] +pub struct WasmTestMessageExt { + pub test_id: u32, +} + +impl WasmTestMessageExt { + pub fn new(test_id: u32) -> Self { + WasmTestMessageExt { test_id } + } +} + +// TODO: maybe put it in the tester utils +#[wasm_bindgen] +pub struct NodeTestResult { + pub sent_packets: u32, + pub received_packets: u32, + pub received_acks: u32, + + pub duplicate_packets: u32, + pub duplicate_acks: u32, +} + +impl Display for NodeTestResult { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + writeln!(f, "Test results: ")?; + writeln!(f, "Total score: {:.2}%", self.score())?; + writeln!(f, "Sent packets: {}", self.sent_packets)?; + writeln!(f, "Received (valid) packets: {}", self.received_packets)?; + writeln!(f, "Received (valid) acks: {}", self.received_acks)?; + writeln!(f, "Received duplicate packets: {}", self.duplicate_packets)?; + write!(f, "Received duplicate acks: {}", self.duplicate_acks) + } +} + +#[wasm_bindgen] +impl NodeTestResult { + pub fn log_details(&self) { + console_log!("{}", self) + } + + pub fn score(&self) -> f32 { + let expected = self.sent_packets * 2; + let actual = (self.received_packets + self.received_acks) + .saturating_sub(self.duplicate_packets + self.duplicate_acks); + + actual as f32 / expected as f32 * 100. + } +} diff --git a/yarn.lock b/yarn.lock index ca5ac7a967..d6dc50eb8e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -34,6 +34,14 @@ dependencies: "@babel/highlight" "^7.22.5" +"@babel/code-frame@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== + dependencies: + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" + "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.5.tgz#b1f6c86a02d85d2dd3368a2b67c09add8cd0c255" @@ -44,6 +52,11 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.6.tgz#15606a20341de59ba02cd2fcc5086fcbe73bf544" integrity sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg== +"@babel/compat-data@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730" + integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ== + "@babel/core@7.12.9": version "7.12.9" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" @@ -108,6 +121,27 @@ gensync "^1.0.0-beta.2" json5 "^2.2.2" +"@babel/core@^7.22.10": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.15.tgz#15d4fd03f478a459015a4b94cfbb3bd42c48d2f4" + integrity sha512-PtZqMmgRrvj8ruoEOIwVA3yoF91O+Hgw9o7DAUTNBA6Mo2jpu31clx9a7Nz/9JznqetTR6zwfC4L3LAjKQXUwA== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.22.15" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-module-transforms" "^7.22.15" + "@babel/helpers" "^7.22.15" + "@babel/parser" "^7.22.15" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.22.15" + "@babel/types" "^7.22.15" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + "@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.22.5", "@babel/generator@^7.7.2": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.5.tgz#1e7bf768688acfb05cf30b2369ef855e82d984f7" @@ -118,6 +152,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.15.tgz#1564189c7ec94cb8f77b5e8a90c4d200d21b2339" + integrity sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA== + dependencies: + "@babel/types" "^7.22.15" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/generator@^7.22.7": version "7.22.7" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.7.tgz#a6b8152d5a621893f2c9dacf9a4e286d520633d5" @@ -153,6 +197,17 @@ lru-cache "^5.1.1" semver "^6.3.0" +"@babel/helper-compilation-targets@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52" + integrity sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-validator-option" "^7.22.15" + browserslist "^4.21.9" + lru-cache "^5.1.1" + semver "^6.3.1" + "@babel/helper-compilation-targets@^7.22.6": version "7.22.6" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz#e30d61abe9480aa5a83232eb31c111be922d2e52" @@ -179,6 +234,21 @@ "@babel/helper-split-export-declaration" "^7.22.5" semver "^6.3.0" +"@babel/helper-create-class-features-plugin@^7.22.11", "@babel/helper-create-class-features-plugin@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz#97a61b385e57fe458496fad19f8e63b63c867de4" + integrity sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" + "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.5.tgz#bb2bf0debfe39b831986a4efbf4066586819c6e4" @@ -214,6 +284,17 @@ resolve "^1.14.2" semver "^6.1.2" +"@babel/helper-define-polyfill-provider@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz#82c825cadeeeee7aad237618ebbe8fa1710015d7" + integrity sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw== + dependencies: + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + "@babel/helper-environment-visitor@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" @@ -234,6 +315,13 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-member-expression-to-functions@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.15.tgz#b95a144896f6d491ca7863576f820f3628818621" + integrity sha512-qLNsZbgrNh0fDQBCPocSL8guki1hcPvltGDv/NxvUoABwFq7GkKSu1nRXeJkVZc+wJvne2E0RKQz+2SQrz6eAA== + dependencies: + "@babel/types" "^7.22.15" + "@babel/helper-member-expression-to-functions@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz#0a7c56117cad3372fbf8d2fb4bf8f8d64a1e76b2" @@ -248,6 +336,13 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== + dependencies: + "@babel/types" "^7.22.15" + "@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz#0f65daa0716961b6e96b164034e737f60a80d2ef" @@ -262,6 +357,17 @@ "@babel/traverse" "^7.22.5" "@babel/types" "^7.22.5" +"@babel/helper-module-transforms@^7.22.15", "@babel/helper-module-transforms@^7.22.9": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.15.tgz#40ad2f6950f143900e9c1c72363c0b431a606082" + integrity sha512-l1UiX4UyHSFsYt17iQ3Se5pQQZZHa22zyIXURmvkmLCD4t/aU+dvNWHatKac/D9Vm9UES7nvIqHs4jZqKviUmQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.15" + "@babel/helper-optimise-call-expression@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" @@ -289,6 +395,15 @@ "@babel/helper-wrap-function" "^7.22.5" "@babel/types" "^7.22.5" +"@babel/helper-remap-async-to-generator@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz#53a25b7484e722d7efb9c350c75c032d4628de82" + integrity sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-wrap-function" "^7.22.9" + "@babel/helper-replace-supers@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.5.tgz#71bc5fb348856dea9fdc4eafd7e2e49f585145dc" @@ -301,6 +416,15 @@ "@babel/traverse" "^7.22.5" "@babel/types" "^7.22.5" +"@babel/helper-replace-supers@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz#cbdc27d6d8d18cd22c81ae4293765a5d9afd0779" + integrity sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg== + dependencies: + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.22.5" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-simple-access@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" @@ -334,11 +458,21 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== +"@babel/helper-validator-identifier@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz#601fa28e4cc06786c18912dca138cec73b882044" + integrity sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ== + "@babel/helper-validator-identifier@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== +"@babel/helper-validator-option@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040" + integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA== + "@babel/helper-validator-option@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac" @@ -354,6 +488,15 @@ "@babel/traverse" "^7.22.5" "@babel/types" "^7.22.5" +"@babel/helper-wrap-function@^7.22.9": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz#d845e043880ed0b8c18bd194a12005cb16d2f614" + integrity sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ== + dependencies: + "@babel/helper-function-name" "^7.22.5" + "@babel/template" "^7.22.5" + "@babel/types" "^7.22.10" + "@babel/helpers@^7.12.5", "@babel/helpers@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.5.tgz#74bb4373eb390d1ceed74a15ef97767e63120820" @@ -363,6 +506,15 @@ "@babel/traverse" "^7.22.5" "@babel/types" "^7.22.5" +"@babel/helpers@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.15.tgz#f09c3df31e86e3ea0b7ff7556d85cdebd47ea6f1" + integrity sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.22.15" + "@babel/types" "^7.22.15" + "@babel/helpers@^7.22.6": version "7.22.6" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.6.tgz#8e61d3395a4f0c5a8060f309fb008200969b5ecd" @@ -381,16 +533,37 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.13.tgz#9cda839e5d3be9ca9e8c26b6dd69e7548f0cbf16" + integrity sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ== + dependencies: + "@babel/helper-validator-identifier" "^7.22.5" + chalk "^2.4.2" + js-tokens "^4.0.0" + "@babel/parser@^7.1.0", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.5.tgz#721fd042f3ce1896238cf1b341c77eb7dee7dbea" integrity sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q== +"@babel/parser@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.15.tgz#d34592bfe288a32e741aa0663dbc4829fcd55160" + integrity sha512-RWmQ/sklUN9BvGGpCDgSubhHWfAx24XDTDObup4ffvxaYsptOg2P3KG0j+1eWKLxpkX0j0uHxmpq2Z1SP/VhxA== + "@babel/parser@^7.22.7": version "7.22.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.7.tgz#df8cf085ce92ddbdbf668a7f186ce848c9036cae" integrity sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz#02dc8a03f613ed5fdc29fb2f728397c78146c962" + integrity sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz#87245a21cd69a73b0b81bcda98d443d6df08f05e" @@ -398,6 +571,15 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz#2aeb91d337d4e1a1e7ce85b76a37f5301781200f" + integrity sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-transform-optional-chaining" "^7.22.15" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz#fef09f9499b1f1c930da8a0c419db42167d792ca" @@ -685,6 +867,16 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-async-generator-functions@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.15.tgz#3b153af4a6b779f340d5b80d3f634f55820aefa3" + integrity sha512-jBm1Es25Y+tVoTi5rfd5t1KLmL8ogLKpXszboWOTTtGFGz2RKnQe2yn7HbZ+kb/B8N0FVSGQo874NSlOU1T4+w== + dependencies: + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-remap-async-to-generator" "^7.22.9" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-transform-async-generator-functions@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.5.tgz#7336356d23380eda9a56314974f053a020dab0c3" @@ -718,6 +910,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-block-scoping@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.15.tgz#494eb82b87b5f8b1d8f6f28ea74078ec0a10a841" + integrity sha512-G1czpdJBZCtngoK1sJgloLiOHUnkb/bLZwqVZD8kXmq0ZnVfTTWUcs9OWtp0mBtYJ+4LQY1fllqBkOIPhXmFmw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-class-properties@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz#97a56e31ad8c9dc06a0b3710ce7803d5a48cca77" @@ -726,6 +925,15 @@ "@babel/helper-create-class-features-plugin" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-class-static-block@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz#dc8cc6e498f55692ac6b4b89e56d87cec766c974" + integrity sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.11" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-transform-class-static-block@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz#3e40c46f048403472d6f4183116d5e46b1bff5ba" @@ -750,6 +958,21 @@ "@babel/helper-split-export-declaration" "^7.22.5" globals "^11.1.0" +"@babel/plugin-transform-classes@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz#aaf4753aee262a232bbc95451b4bdf9599c65a0b" + integrity sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-split-export-declaration" "^7.22.6" + globals "^11.1.0" + "@babel/plugin-transform-computed-properties@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz#cd1e994bf9f316bd1c2dafcd02063ec261bb3869" @@ -765,6 +988,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-destructuring@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.15.tgz#e7404ea5bb3387073b9754be654eecb578324694" + integrity sha512-HzG8sFl1ZVGTme74Nw+X01XsUTqERVQ6/RLHo3XjGRzm7XD6QTtfS3NJotVgCGy8BzkDqRjRBD8dAyJn5TuvSQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-dotall-regex@^7.22.5", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz#dbb4f0e45766eb544e193fb00e65a1dd3b2a4165" @@ -780,6 +1010,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-dynamic-import@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz#2c7722d2a5c01839eaf31518c6ff96d408e447aa" + integrity sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-transform-dynamic-import@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz#d6908a8916a810468c4edff73b5b75bda6ad393e" @@ -796,6 +1034,14 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-export-namespace-from@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz#b3c84c8f19880b6c7440108f8929caf6056db26c" + integrity sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-transform-export-namespace-from@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz#57c41cb1d0613d22f548fddd8b288eedb9973a5b" @@ -819,6 +1065,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-for-of@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz#f64b4ccc3a4f131a996388fae7680b472b306b29" + integrity sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-function-name@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz#935189af68b01898e0d6d99658db6b164205c143" @@ -828,6 +1081,14 @@ "@babel/helper-function-name" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-json-strings@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz#689a34e1eed1928a40954e37f74509f48af67835" + integrity sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-transform-json-strings@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz#14b64352fdf7e1f737eed68de1a1468bd2a77ec0" @@ -843,6 +1104,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-logical-assignment-operators@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz#24c522a61688bde045b7d9bc3c2597a4d948fc9c" + integrity sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-transform-logical-assignment-operators@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz#66ae5f068fd5a9a5dc570df16f56c2a8462a9d6c" @@ -866,6 +1135,15 @@ "@babel/helper-module-transforms" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-modules-commonjs@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.15.tgz#b11810117ed4ee7691b29bd29fd9f3f98276034f" + integrity sha512-jWL4eh90w0HQOTKP2MoXXUpVxilxsB2Vl4ji69rSjS3EcZ/v4sBmn+A3NpepuJzBhOaEBbR7udonlHHn5DWidg== + dependencies: + "@babel/helper-module-transforms" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" + "@babel/plugin-transform-modules-commonjs@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz#7d9875908d19b8c0536085af7b053fd5bd651bfa" @@ -875,6 +1153,16 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-simple-access" "^7.22.5" +"@babel/plugin-transform-modules-systemjs@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.11.tgz#3386be5875d316493b517207e8f1931d93154bb1" + integrity sha512-rIqHmHoMEOhI3VkVf5jQ15l539KrwhzqcBO6wdCNWPWc/JWt9ILNYNUssbRpeq0qWns8svuw8LnMNCvWBIJ8wA== + dependencies: + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-module-transforms" "^7.22.9" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" + "@babel/plugin-transform-modules-systemjs@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz#18c31410b5e579a0092638f95c896c2a98a5d496" @@ -908,6 +1196,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-nullish-coalescing-operator@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz#debef6c8ba795f5ac67cd861a81b744c5d38d9fc" + integrity sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-transform-nullish-coalescing-operator@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz#f8872c65776e0b552e0849d7596cddd416c3e381" @@ -916,6 +1212,14 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" +"@babel/plugin-transform-numeric-separator@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz#498d77dc45a6c6db74bb829c02a01c1d719cbfbd" + integrity sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-transform-numeric-separator@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz#57226a2ed9e512b9b446517ab6fa2d17abb83f58" @@ -924,6 +1228,17 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-numeric-separator" "^7.10.4" +"@babel/plugin-transform-object-rest-spread@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz#21a95db166be59b91cde48775310c0df6e1da56f" + integrity sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.22.15" + "@babel/plugin-transform-object-rest-spread@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz#9686dc3447df4753b0b2a2fae7e8bc33cdc1f2e1" @@ -943,6 +1258,14 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-replace-supers" "^7.22.5" +"@babel/plugin-transform-optional-catch-binding@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz#461cc4f578a127bb055527b3e77404cad38c08e0" + integrity sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-transform-optional-catch-binding@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz#842080be3076703be0eaf32ead6ac8174edee333" @@ -951,6 +1274,15 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" +"@babel/plugin-transform-optional-chaining@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.15.tgz#d7a5996c2f7ca4ad2ad16dbb74444e5c4385b1ba" + integrity sha512-ngQ2tBhq5vvSJw2Q2Z9i7ealNkpDMU0rGWnHPKqRZO0tzZ5tlaoz4hDvhXioOoaE0X2vfNss1djwg0DXlfu30A== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-transform-optional-chaining@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.5.tgz#1003762b9c14295501beb41be72426736bedd1e0" @@ -967,6 +1299,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-parameters@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz#719ca82a01d177af358df64a514d64c2e3edb114" + integrity sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-private-methods@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz#21c8af791f76674420a147ae62e9935d790f8722" @@ -975,6 +1314,16 @@ "@babel/helper-create-class-features-plugin" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-private-property-in-object@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz#ad45c4fc440e9cb84c718ed0906d96cf40f9a4e1" + integrity sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.11" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-transform-private-property-in-object@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz#07a77f28cbb251546a43d175a1dda4cf3ef83e32" @@ -1032,6 +1381,14 @@ "@babel/helper-annotate-as-pure" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-regenerator@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz#8ceef3bd7375c4db7652878b0241b2be5d0c3cca" + integrity sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + regenerator-transform "^0.15.2" + "@babel/plugin-transform-regenerator@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.5.tgz#cd8a68b228a5f75fa01420e8cc2fc400f0fc32aa" @@ -1083,6 +1440,16 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-typescript@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.15.tgz#15adef906451d86349eb4b8764865c960eb54127" + integrity sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-typescript" "^7.22.5" + "@babel/plugin-transform-typescript@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.5.tgz#5c0f7adfc1b5f38c4dbc8f79b1f0f8074134bd7d" @@ -1093,6 +1460,13 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-typescript" "^7.22.5" +"@babel/plugin-transform-unicode-escapes@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz#c723f380f40a2b2f57a62df24c9005834c8616d9" + integrity sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-unicode-escapes@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.5.tgz#ce0c248522b1cb22c7c992d88301a5ead70e806c" @@ -1210,6 +1584,92 @@ core-js-compat "^3.30.2" semver "^6.3.0" +"@babel/preset-env@^7.22.10": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.22.15.tgz#142716f8e00bc030dae5b2ac6a46fbd8b3e18ff8" + integrity sha512-tZFHr54GBkHk6hQuVA8w4Fmq+MSPsfvMG0vPnOYyTnJpyfMqybL8/MbNCPRT9zc2KBO2pe4tq15g6Uno4Jpoag== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.15" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.22.15" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.22.15" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.22.5" + "@babel/plugin-syntax-import-attributes" "^7.22.5" + "@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/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.22.5" + "@babel/plugin-transform-async-generator-functions" "^7.22.15" + "@babel/plugin-transform-async-to-generator" "^7.22.5" + "@babel/plugin-transform-block-scoped-functions" "^7.22.5" + "@babel/plugin-transform-block-scoping" "^7.22.15" + "@babel/plugin-transform-class-properties" "^7.22.5" + "@babel/plugin-transform-class-static-block" "^7.22.11" + "@babel/plugin-transform-classes" "^7.22.15" + "@babel/plugin-transform-computed-properties" "^7.22.5" + "@babel/plugin-transform-destructuring" "^7.22.15" + "@babel/plugin-transform-dotall-regex" "^7.22.5" + "@babel/plugin-transform-duplicate-keys" "^7.22.5" + "@babel/plugin-transform-dynamic-import" "^7.22.11" + "@babel/plugin-transform-exponentiation-operator" "^7.22.5" + "@babel/plugin-transform-export-namespace-from" "^7.22.11" + "@babel/plugin-transform-for-of" "^7.22.15" + "@babel/plugin-transform-function-name" "^7.22.5" + "@babel/plugin-transform-json-strings" "^7.22.11" + "@babel/plugin-transform-literals" "^7.22.5" + "@babel/plugin-transform-logical-assignment-operators" "^7.22.11" + "@babel/plugin-transform-member-expression-literals" "^7.22.5" + "@babel/plugin-transform-modules-amd" "^7.22.5" + "@babel/plugin-transform-modules-commonjs" "^7.22.15" + "@babel/plugin-transform-modules-systemjs" "^7.22.11" + "@babel/plugin-transform-modules-umd" "^7.22.5" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" + "@babel/plugin-transform-new-target" "^7.22.5" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.22.11" + "@babel/plugin-transform-numeric-separator" "^7.22.11" + "@babel/plugin-transform-object-rest-spread" "^7.22.15" + "@babel/plugin-transform-object-super" "^7.22.5" + "@babel/plugin-transform-optional-catch-binding" "^7.22.11" + "@babel/plugin-transform-optional-chaining" "^7.22.15" + "@babel/plugin-transform-parameters" "^7.22.15" + "@babel/plugin-transform-private-methods" "^7.22.5" + "@babel/plugin-transform-private-property-in-object" "^7.22.11" + "@babel/plugin-transform-property-literals" "^7.22.5" + "@babel/plugin-transform-regenerator" "^7.22.10" + "@babel/plugin-transform-reserved-words" "^7.22.5" + "@babel/plugin-transform-shorthand-properties" "^7.22.5" + "@babel/plugin-transform-spread" "^7.22.5" + "@babel/plugin-transform-sticky-regex" "^7.22.5" + "@babel/plugin-transform-template-literals" "^7.22.5" + "@babel/plugin-transform-typeof-symbol" "^7.22.5" + "@babel/plugin-transform-unicode-escapes" "^7.22.10" + "@babel/plugin-transform-unicode-property-regex" "^7.22.5" + "@babel/plugin-transform-unicode-regex" "^7.22.5" + "@babel/plugin-transform-unicode-sets-regex" "^7.22.5" + "@babel/preset-modules" "0.1.6-no-external-plugins" + "@babel/types" "^7.22.15" + babel-plugin-polyfill-corejs2 "^0.4.5" + babel-plugin-polyfill-corejs3 "^0.8.3" + babel-plugin-polyfill-regenerator "^0.5.2" + core-js-compat "^3.31.0" + semver "^6.3.1" + "@babel/preset-flow@^7.12.1": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.22.5.tgz#876f24ab6b38bd79703a93f32020ca2162312784" @@ -1219,6 +1679,15 @@ "@babel/helper-validator-option" "^7.22.5" "@babel/plugin-transform-flow-strip-types" "^7.22.5" +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + "@babel/preset-modules@^0.1.5": version "0.1.5" resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" @@ -1253,6 +1722,17 @@ "@babel/plugin-transform-modules-commonjs" "^7.22.5" "@babel/plugin-transform-typescript" "^7.22.5" +"@babel/preset-typescript@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.22.15.tgz#43db30516fae1d417d748105a0bc95f637239d48" + integrity sha512-HblhNmh6yM+cU4VwbBRpxFhxsTdfS1zsvH9W+gEjD0ARV9+8B4sNfpI6GuhePti84nuvhiwKS539jKPFHskA9A== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.15" + "@babel/plugin-syntax-jsx" "^7.22.5" + "@babel/plugin-transform-modules-commonjs" "^7.22.15" + "@babel/plugin-transform-typescript" "^7.22.15" + "@babel/register@^7.12.1": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.22.5.tgz#e4d8d0f615ea3233a27b5c6ada6750ee59559939" @@ -1299,6 +1779,15 @@ "@babel/parser" "^7.22.5" "@babel/types" "^7.22.5" +"@babel/template@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + "@babel/traverse@^7.1.6", "@babel/traverse@^7.12.11", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.22.5", "@babel/traverse@^7.7.2": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.5.tgz#44bd276690db6f4940fdb84e1cb4abd2f729ccd1" @@ -1315,6 +1804,22 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.15.tgz#75be4d2d6e216e880e93017f4e2389aeb77ef2d9" + integrity sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.22.15" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + debug "^4.1.0" + globals "^11.1.0" + "@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8": version "7.22.8" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.8.tgz#4d4451d31bc34efeae01eac222b514a77aa4000e" @@ -1340,6 +1845,15 @@ "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" +"@babel/types@^7.22.10", "@babel/types@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.15.tgz#266cb21d2c5fd0b3931e7a91b6dd72d2f617d282" + integrity sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.15" + to-fast-properties "^2.0.0" + "@base2/pretty-print-object@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz#371ba8be66d556812dc7fb169ebc3c08378f69d4" @@ -2245,6 +2759,13 @@ dependencies: "@sinclair/typebox" "^0.27.8" +"@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@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf" @@ -2424,6 +2945,18 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" +"@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.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.3" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" @@ -2690,7 +3223,7 @@ resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.13.4.tgz#7e4b491d8081b6d45ae51556d82cb16b31315a19" integrity sha512-yFrMWcrlI0TqRN5jpb6Ma9iI7sGTHpytdzzL33oskFHNQ8UgrtPas33Y1K7sWAMwCrr1qbWDrOHLAQG4tAzuSw== -"@mui/icons-material@^5.0.0", "@mui/icons-material@^5.2.0", "@mui/icons-material@^5.5.0": +"@mui/icons-material@^5.0.0", "@mui/icons-material@^5.2.0": version "5.11.16" resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.11.16.tgz#417fa773c56672e39d6ccfed9ac55591985f0d38" integrity sha512-oKkx9z9Kwg40NtcIajF9uOXhxiyTZrrm9nmIJ4UjkU2IdHpd4QVLbCc/5hZN/y0C6qzi2Zlxyr9TGddQx2vx2A== @@ -3130,11 +3663,6 @@ "@cosmjs/stargate" "^0.25.5" axios "^0.21.1" -"@nymproject/sdk@^1.1.8": - version "1.1.8" - resolved "https://registry.yarnpkg.com/@nymproject/sdk/-/sdk-1.1.8.tgz#384ee824971dee413755b14634c3d60fb22eff9a" - integrity sha512-nAyem2wqTfc6l9e6Y7JR2V1teDfwjxMHpRjxg90FMkUWl/JP7Ww752gDsSq3nvObLt+cvxjWMHy1mswvwQfZyQ== - "@octokit/auth-token@^3.0.0": version "3.0.4" resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-3.0.4.tgz#70e941ba742bdd2b49bdb7393e821dea8520a3db" @@ -3427,6 +3955,15 @@ "@rollup/pluginutils" "^5.0.1" resolve "^1.22.1" +"@rollup/plugin-url@^8.0.1": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-url/-/plugin-url-8.0.1.tgz#8da005d4be8cb4439357c929c73c85ceb5d979a4" + integrity sha512-8ajztphXb5e19dk3Iwjtm2eSYJR8jFQubZ8pJ1GG2MBMM7/qUedLnZAN+Vt4jqbcT/m27jfjIBocvrzV0giNRw== + dependencies: + "@rollup/pluginutils" "^5.0.1" + make-dir "^3.1.0" + mime "^3.0.0" + "@rollup/plugin-wasm@^6.1.1": version "6.1.3" resolved "https://registry.yarnpkg.com/@rollup/plugin-wasm/-/plugin-wasm-6.1.3.tgz#8d26a320780b15bf89d8d266ceda50823d5f978b" @@ -5993,6 +6530,11 @@ resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== +"@webpack-cli/configtest@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" + integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== + "@webpack-cli/info@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" @@ -6000,11 +6542,21 @@ dependencies: envinfo "^7.7.3" +"@webpack-cli/info@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" + integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== + "@webpack-cli/serve@^1.7.0": version "1.7.0" resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== +"@webpack-cli/serve@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" + integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -6267,9 +6819,9 @@ ansi-regex@^6.0.1: integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== ansi-sequence-parser@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz#4d790f31236ac20366b23b3916b789e1bde39aed" - integrity sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ== + version "1.1.1" + resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz#e0aa1cdcbc8f8bb0b5bca625aac41f5f056973cf" + integrity sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg== ansi-styles@^3.2.1: version "3.2.1" @@ -6690,6 +7242,14 @@ babel-loader@^8.0.0, babel-loader@^8.2.3, babel-loader@^8.3.0: make-dir "^3.1.0" schema-utils "^2.6.5" +babel-loader@^9.1.3: + version "9.1.3" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.1.3.tgz#3d0e01b4e69760cc694ee306fe16d358aa1c6f9a" + integrity sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw== + dependencies: + find-cache-dir "^4.0.0" + schema-utils "^4.0.0" + babel-plugin-add-react-displayname@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/babel-plugin-add-react-displayname/-/babel-plugin-add-react-displayname-0.0.5.tgz#339d4cddb7b65fd62d1df9db9fe04de134122bd5" @@ -6764,6 +7324,15 @@ babel-plugin-polyfill-corejs2@^0.4.3: "@babel/helper-define-polyfill-provider" "^0.4.0" semver "^6.1.1" +babel-plugin-polyfill-corejs2@^0.4.5: + version "0.4.5" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz#8097b4cb4af5b64a1d11332b6fb72ef5e64a054c" + integrity sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg== + dependencies: + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.4.2" + semver "^6.3.1" + babel-plugin-polyfill-corejs3@^0.1.0: version "0.1.7" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz#80449d9d6f2274912e05d9e182b54816904befd0" @@ -6780,6 +7349,14 @@ babel-plugin-polyfill-corejs3@^0.8.1: "@babel/helper-define-polyfill-provider" "^0.4.0" core-js-compat "^3.30.1" +babel-plugin-polyfill-corejs3@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz#b4f719d0ad9bb8e0c23e3e630c0c8ec6dd7a1c52" + integrity sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.4.2" + core-js-compat "^3.31.0" + babel-plugin-polyfill-regenerator@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.0.tgz#e7344d88d9ef18a3c47ded99362ae4a757609380" @@ -6787,6 +7364,13 @@ babel-plugin-polyfill-regenerator@^0.5.0: dependencies: "@babel/helper-define-polyfill-provider" "^0.4.0" +babel-plugin-polyfill-regenerator@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz#80d0f3e1098c080c8b5a65f41e9427af692dc326" + integrity sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.4.2" + babel-plugin-react-docgen@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/babel-plugin-react-docgen/-/babel-plugin-react-docgen-4.2.1.tgz#7cc8e2f94e8dc057a06e953162f0810e4e72257b" @@ -7162,6 +7746,16 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4 node-releases "^2.0.12" update-browserslist-db "^1.0.11" +browserslist@^4.21.10: + version "4.21.10" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.10.tgz#dbbac576628c13d3b2231332cb2ec5a46e015bb0" + integrity sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ== + dependencies: + caniuse-lite "^1.0.30001517" + electron-to-chromium "^1.4.477" + node-releases "^2.0.13" + update-browserslist-db "^1.0.11" + bs-logger@0.x: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" @@ -7453,6 +8047,11 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001503: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001509.tgz#2b7ad5265392d6d2de25cd8776d1ab3899570d14" integrity sha512-2uDDk+TRiTX5hMcUYT/7CSyzMZxjfGu0vAUjS2g0LSD8UoXOv0LtpH4LxGMemsiPq6LCVIUjNwVM0erkOkGCDA== +caniuse-lite@^1.0.30001517: + version "1.0.30001527" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001527.tgz#813826554828245ccee776c850566dce12bdeaba" + integrity sha512-YkJi7RwPgWtXVSgK4lG9AHH57nSzvvOp9MesgXmw4Q7n0C3H04L0foHqfxcmSAm5AcWb8dW9AYj2tR7/5GnddQ== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -7483,7 +8082,7 @@ chalk@4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^2.0.0, chalk@^2.4.1: +chalk@^2.0.0, chalk@^2.4.1, 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== @@ -7924,6 +8523,11 @@ commander@2, commander@^2.19.0, commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + commander@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" @@ -8191,6 +8795,18 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== +copy-webpack-plugin@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a" + integrity sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ== + dependencies: + fast-glob "^3.2.11" + glob-parent "^6.0.1" + globby "^13.1.1" + normalize-path "^3.0.0" + schema-utils "^4.0.0" + serialize-javascript "^6.0.0" + core-js-compat@^3.30.1, core-js-compat@^3.30.2, core-js-compat@^3.8.1: version "3.31.0" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.31.0.tgz#4030847c0766cc0e803dcdfb30055d7ef2064bf1" @@ -8198,6 +8814,13 @@ core-js-compat@^3.30.1, core-js-compat@^3.30.2, core-js-compat@^3.8.1: dependencies: browserslist "^4.21.5" +core-js-compat@^3.31.0: + version "3.32.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.32.1.tgz#55f9a7d297c0761a8eb1d31b593e0f5b6ffae964" + integrity sha512-GSvKDv4wE0bPnQtjklV101juQ85g6H3rm5PDP20mqlS5j0kXF3pP97YvAu5hl+uFHqMictp3b2VxOHljWMAtuA== + dependencies: + browserslist "^4.21.10" + core-js-pure@^3.23.3: version "3.31.0" resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.31.0.tgz#052fd9e82fbaaf86457f5db1fadcd06f15966ff2" @@ -8405,7 +9028,7 @@ css-loader@^5.0.1: schema-utils "^3.0.0" semver "^7.3.5" -css-loader@^6.7.3: +css-loader@^6.7.3, css-loader@^6.8.1: version "6.8.1" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.8.1.tgz#0f8f52699f60f5e679eab4ec0fcd68b8e8a50a88" integrity sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g== @@ -8431,6 +9054,18 @@ css-minimizer-webpack-plugin@^3.0.2: serialize-javascript "^6.0.0" source-map "^0.6.1" +css-minimizer-webpack-plugin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz#33effe662edb1a0bf08ad633c32fa75d0f7ec565" + integrity sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + cssnano "^6.0.1" + jest-worker "^29.4.3" + postcss "^8.4.24" + schema-utils "^4.0.1" + serialize-javascript "^6.0.1" + css-select@^4.1.3: version "4.3.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" @@ -8442,6 +9077,17 @@ css-select@^4.1.3: domutils "^2.8.0" nth-check "^2.0.1" +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" + css-tree@^1.1.2, css-tree@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" @@ -8450,6 +9096,22 @@ css-tree@^1.1.2, css-tree@^1.1.3: mdn-data "2.0.14" source-map "^0.6.1" +css-tree@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.3.1.tgz#10264ce1e5442e8572fc82fbe490644ff54b5c20" + integrity sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw== + dependencies: + mdn-data "2.0.30" + source-map-js "^1.0.1" + +css-tree@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.2.1.tgz#36115d382d60afd271e377f9c5f67d02bd48c032" + integrity sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA== + dependencies: + mdn-data "2.0.28" + source-map-js "^1.0.1" + css-unit-converter@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21" @@ -8463,7 +9125,7 @@ css-vendor@^2.0.8: "@babel/runtime" "^7.8.3" is-in-browser "^1.0.2" -css-what@^6.0.1: +css-what@^6.0.1, css-what@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== @@ -8513,11 +9175,51 @@ cssnano-preset-default@^5.2.14: postcss-svgo "^5.1.0" postcss-unique-selectors "^5.1.1" +cssnano-preset-default@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-6.0.1.tgz#2a93247140d214ddb9f46bc6a3562fa9177fe301" + integrity sha512-7VzyFZ5zEB1+l1nToKyrRkuaJIx0zi/1npjvZfbBwbtNTzhLtlvYraK/7/uqmX2Wb2aQtd983uuGw79jAjLSuQ== + dependencies: + css-declaration-sorter "^6.3.1" + cssnano-utils "^4.0.0" + postcss-calc "^9.0.0" + postcss-colormin "^6.0.0" + postcss-convert-values "^6.0.0" + postcss-discard-comments "^6.0.0" + postcss-discard-duplicates "^6.0.0" + postcss-discard-empty "^6.0.0" + postcss-discard-overridden "^6.0.0" + postcss-merge-longhand "^6.0.0" + postcss-merge-rules "^6.0.1" + postcss-minify-font-values "^6.0.0" + postcss-minify-gradients "^6.0.0" + postcss-minify-params "^6.0.0" + postcss-minify-selectors "^6.0.0" + postcss-normalize-charset "^6.0.0" + postcss-normalize-display-values "^6.0.0" + postcss-normalize-positions "^6.0.0" + postcss-normalize-repeat-style "^6.0.0" + postcss-normalize-string "^6.0.0" + postcss-normalize-timing-functions "^6.0.0" + postcss-normalize-unicode "^6.0.0" + postcss-normalize-url "^6.0.0" + postcss-normalize-whitespace "^6.0.0" + postcss-ordered-values "^6.0.0" + postcss-reduce-initial "^6.0.0" + postcss-reduce-transforms "^6.0.0" + postcss-svgo "^6.0.0" + postcss-unique-selectors "^6.0.0" + cssnano-utils@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== +cssnano-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-4.0.0.tgz#d1da885ec04003ab19505ff0e62e029708d36b08" + integrity sha512-Z39TLP+1E0KUcd7LGyF4qMfu8ZufI0rDzhdyAMsa/8UyNUU8wpS0fhdBxbQbv32r64ea00h4878gommRVg2BHw== + cssnano@^5.0.6: version "5.1.15" resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.15.tgz#ded66b5480d5127fcb44dac12ea5a983755136bf" @@ -8527,6 +9229,14 @@ cssnano@^5.0.6: lilconfig "^2.0.3" yaml "^1.10.2" +cssnano@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-6.0.1.tgz#87c38c4cd47049c735ab756d7e77ac3ca855c008" + integrity sha512-fVO1JdJ0LSdIGJq68eIxOqFpIJrZqXUsBt8fkrBcztCQqAjQD51OhZp7tc0ImcbwXD4k7ny84QTV90nZhmqbkg== + dependencies: + cssnano-preset-default "^6.0.1" + lilconfig "^2.1.0" + csso@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" @@ -8534,6 +9244,13 @@ csso@^4.2.0: dependencies: css-tree "^1.1.2" +csso@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/csso/-/csso-5.0.5.tgz#f9b7fe6cc6ac0b7d90781bb16d5e9874303e2ca6" + integrity sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ== + dependencies: + css-tree "~2.2.0" + cssom@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" @@ -9166,6 +9883,15 @@ dom-serializer@^1.0.1: domhandler "^4.2.0" entities "^2.0.0" +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + dom-walk@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" @@ -9176,7 +9902,7 @@ domain-browser@^1.1.1: resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== -domelementtype@^2.0.1, domelementtype@^2.2.0: +domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== @@ -9195,6 +9921,13 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: dependencies: domelementtype "^2.2.0" +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" @@ -9204,6 +9937,15 @@ domutils@^2.5.2, domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" +domutils@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + dot-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" @@ -9245,6 +9987,13 @@ dotenv-webpack@^7.0.3: dependencies: dotenv-defaults "^2.0.2" +dotenv-webpack@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/dotenv-webpack/-/dotenv-webpack-8.0.1.tgz#6656550460a8076fab20e5ac2eac867e72478645" + integrity sha512-CdrgfhZOnx4uB18SgaoP9XHRN2v48BbjuXQsZY5ixs5A8579NxQkmMxRtI7aTwSiSQcM2ao12Fdu+L3ZS3bG4w== + dependencies: + dotenv-defaults "^2.0.2" + dotenv@^16.0.3: version "16.3.1" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" @@ -9297,6 +10046,11 @@ electron-to-chromium@^1.4.431: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.445.tgz#058d2c5f3a2981ab1a37440f5a5e42d15672aa6d" integrity sha512-++DB+9VK8SBJwC+X1zlMfJ1tMA3F0ipi39GdEp+x3cV2TyBihqAgad8cNMWtLDEkbH39nlDQP7PfGrDr3Dr7HA== +electron-to-chromium@^1.4.477: + version "1.4.508" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.508.tgz#5641ff2f5ba11df4bd960fe6a2f9f70aa8b9af96" + integrity sha512-FFa8QKjQK/A5QuFr2167myhMesGrhlOBD+3cYNxO9/S4XzHEXesyTD/1/xF644gC8buFPz3ca6G1LOQD0tZrrg== + elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" @@ -9392,7 +10146,7 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== -entities@^4.4.0: +entities@^4.2.0, entities@^4.4.0: version "4.5.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== @@ -10307,6 +11061,17 @@ fast-glob@^2.2.6: merge2 "^1.2.3" micromatch "^3.1.10" +fast-glob@^3.2.11, fast-glob@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" @@ -10506,6 +11271,14 @@ find-cache-dir@^3.3.1: make-dir "^3.0.2" pkg-dir "^4.1.0" +find-cache-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-4.0.0.tgz#a30ee0448f81a3990708f6453633c733e2f6eec2" + integrity sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg== + dependencies: + common-path-prefix "^3.0.0" + pkg-dir "^7.0.0" + find-root@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" @@ -10549,6 +11322,14 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-up@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" + integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== + dependencies: + locate-path "^7.1.0" + path-exists "^5.0.0" + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -10665,6 +11446,24 @@ fork-ts-checker-webpack-plugin@^7.2.1: semver "^7.3.5" tapable "^2.2.1" +fork-ts-checker-webpack-plugin@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz#dae45dfe7298aa5d553e2580096ced79b6179504" + integrity sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg== + dependencies: + "@babel/code-frame" "^7.16.7" + chalk "^4.1.2" + chokidar "^3.5.3" + cosmiconfig "^7.0.1" + deepmerge "^4.2.2" + fs-extra "^10.0.0" + memfs "^3.4.1" + minimatch "^3.0.4" + node-abort-controller "^3.0.1" + schema-utils "^3.1.1" + semver "^7.3.5" + tapable "^2.2.1" + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -11005,7 +11804,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^6.0.2: +glob-parent@^6.0.1, glob-parent@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== @@ -11136,6 +11935,17 @@ globby@11.1.0, globby@^11.0.1, globby@^11.0.2, globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" +globby@^13.1.1: + version "13.2.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" + integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== + dependencies: + dir-glob "^3.0.1" + fast-glob "^3.3.0" + ignore "^5.2.4" + merge2 "^1.4.1" + slash "^4.0.0" + globby@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" @@ -11532,7 +12342,7 @@ html-void-elements@^1.0.0: resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== -html-webpack-plugin@>=5.0.0, html-webpack-plugin@^5.0.0, html-webpack-plugin@^5.3.2: +html-webpack-plugin@>=5.0.0, html-webpack-plugin@^5.0.0, html-webpack-plugin@^5.3.2, html-webpack-plugin@^5.5.3: version "5.5.3" resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz#72270f4a78e222b5825b296e5e3e1328ad525a3e" integrity sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg== @@ -11739,7 +12549,7 @@ ignore@^4.0.3, ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.0.4, ignore@^5.2.0: +ignore@^5.0.4, ignore@^5.2.0, ignore@^5.2.4: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== @@ -11899,6 +12709,11 @@ interpret@^2.2.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== +interpret@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" + integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== + ip@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" @@ -13393,6 +14208,18 @@ jest-util@^29.5.0: graceful-fs "^4.2.9" picomatch "^2.2.3" +jest-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.6.3.tgz#e15c3eac8716440d1ed076f09bc63ace1aebca63" + integrity sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA== + 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@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067" @@ -13462,6 +14289,16 @@ jest-worker@^27.0.2, jest-worker@^27.4.5, jest-worker@^27.5.1: merge-stream "^2.0.0" supports-color "^8.0.0" +jest-worker@^29.4.3: + version "29.6.4" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.6.4.tgz#f34279f4afc33c872b470d4af21b281ac616abd3" + integrity sha512-6dpvFV4WjcWbDVGgHTWo/aupl8/LbBx2NSKfiwqf79xC/yeJjKHT1+StcKy/2KTmW16hE68ccKVOtXf+WZGz7Q== + dependencies: + "@types/node" "*" + jest-util "^29.6.3" + merge-stream "^2.0.0" + supports-color "^8.0.0" + jest-worker@^29.6.1: version "29.6.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.6.1.tgz#64b015f0e985ef3a8ad049b61fe92b3db74a5319" @@ -13946,7 +14783,7 @@ lie@3.1.1: dependencies: immediate "~3.0.5" -lilconfig@^2.0.3: +lilconfig@^2.0.3, lilconfig@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== @@ -14057,6 +14894,13 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +locate-path@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.2.0.tgz#69cb1779bd90b35ab1e771e1f2f89a202c2a8a8a" + integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== + dependencies: + p-locate "^6.0.0" + lodash-es@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" @@ -14511,6 +15355,16 @@ mdn-data@2.0.14: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== +mdn-data@2.0.28: + version "2.0.28" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.28.tgz#5ec48e7bef120654539069e1ae4ddc81ca490eba" + integrity sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g== + +mdn-data@2.0.30: + version "2.0.30" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.30.tgz#ce4df6f80af6cfbe218ecd5c552ba13c4dfa08cc" + integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA== + mdurl@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" @@ -14981,6 +15835,11 @@ mime@^2.4.4: resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -15008,7 +15867,7 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -mini-css-extract-plugin@^2.2.2: +mini-css-extract-plugin@^2.2.2, mini-css-extract-plugin@^2.7.6: version "2.7.6" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz#282a3d38863fddcd2e0c220aaed5b90bc156564d" integrity sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw== @@ -15525,6 +16384,11 @@ node-releases@^2.0.12: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039" integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ== +node-releases@^2.0.13: + version "2.0.13" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" + integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== + nodemon@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.0.1.tgz#affe822a2c5f21354466b2fc8ae83277d27dadc7" @@ -16167,6 +17031,13 @@ p-limit@^3.0.2, p-limit@^3.1.0: dependencies: yocto-queue "^0.1.0" +p-limit@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" + integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== + dependencies: + yocto-queue "^1.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -16195,6 +17066,13 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-locate@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" + integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== + dependencies: + p-limit "^4.0.0" + p-map-series@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-2.1.0.tgz#7560d4c452d9da0c07e692fdbfe6e2c81a2a91f2" @@ -16498,6 +17376,11 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== +path-exists@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" + integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== + 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" @@ -16655,6 +17538,13 @@ pkg-dir@^5.0.0: dependencies: find-up "^5.0.0" +pkg-dir@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-7.0.0.tgz#8f0c08d6df4476756c5ff29b3282d0bab7517d11" + integrity sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA== + dependencies: + find-up "^6.3.0" + pnp-webpack-plugin@1.6.4: version "1.6.4" resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" @@ -16682,6 +17572,14 @@ postcss-calc@^8.2.3: postcss-selector-parser "^6.0.9" postcss-value-parser "^4.2.0" +postcss-calc@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-9.0.1.tgz#a744fd592438a93d6de0f1434c572670361eb6c6" + integrity sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ== + dependencies: + postcss-selector-parser "^6.0.11" + postcss-value-parser "^4.2.0" + postcss-colormin@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.1.tgz#86c27c26ed6ba00d96c79e08f3ffb418d1d1988f" @@ -16692,6 +17590,16 @@ postcss-colormin@^5.3.1: colord "^2.9.1" postcss-value-parser "^4.2.0" +postcss-colormin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-6.0.0.tgz#d4250652e952e1c0aca70c66942da93d3cdeaafe" + integrity sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw== + dependencies: + browserslist "^4.21.4" + caniuse-api "^3.0.0" + colord "^2.9.1" + postcss-value-parser "^4.2.0" + postcss-convert-values@^5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz#04998bb9ba6b65aa31035d669a6af342c5f9d393" @@ -16700,26 +17608,54 @@ postcss-convert-values@^5.1.3: browserslist "^4.21.4" postcss-value-parser "^4.2.0" +postcss-convert-values@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-6.0.0.tgz#ec94a954957e5c3f78f0e8f65dfcda95280b8996" + integrity sha512-U5D8QhVwqT++ecmy8rnTb+RL9n/B806UVaS3m60lqle4YDFcpbS3ae5bTQIh3wOGUSDHSEtMYLs/38dNG7EYFw== + dependencies: + browserslist "^4.21.4" + postcss-value-parser "^4.2.0" + postcss-discard-comments@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696" integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ== +postcss-discard-comments@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-6.0.0.tgz#9ca335e8b68919f301b24ba47dde226a42e535fe" + integrity sha512-p2skSGqzPMZkEQvJsgnkBhCn8gI7NzRH2683EEjrIkoMiwRELx68yoUJ3q3DGSGuQ8Ug9Gsn+OuDr46yfO+eFw== + postcss-discard-duplicates@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== +postcss-discard-duplicates@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.0.tgz#c26177a6c33070922e67e9a92c0fd23d443d1355" + integrity sha512-bU1SXIizMLtDW4oSsi5C/xHKbhLlhek/0/yCnoMQany9k3nPBq+Ctsv/9oMmyqbR96HYHxZcHyK2HR5P/mqoGA== + postcss-discard-empty@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz#e57762343ff7f503fe53fca553d18d7f0c369c6c" integrity sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A== +postcss-discard-empty@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-6.0.0.tgz#06c1c4fce09e22d2a99e667c8550eb8a3a1b9aee" + integrity sha512-b+h1S1VT6dNhpcg+LpyiUrdnEZfICF0my7HAKgJixJLW7BnNmpRH34+uw/etf5AhOlIhIAuXApSzzDzMI9K/gQ== + postcss-discard-overridden@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== +postcss-discard-overridden@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-6.0.0.tgz#49c5262db14e975e349692d9024442de7cd8e234" + integrity sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw== + postcss-flexbugs-fixes@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz#9218a65249f30897deab1033aced8578562a6690" @@ -16746,6 +17682,14 @@ postcss-merge-longhand@^5.1.7: postcss-value-parser "^4.2.0" stylehacks "^5.1.1" +postcss-merge-longhand@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-6.0.0.tgz#6f627b27db939bce316eaa97e22400267e798d69" + integrity sha512-4VSfd1lvGkLTLYcxFuISDtWUfFS4zXe0FpF149AyziftPFQIWxjvFSKhA4MIxMe4XM3yTDgQMbSNgzIVxChbIg== + dependencies: + postcss-value-parser "^4.2.0" + stylehacks "^6.0.0" + postcss-merge-rules@^5.1.4: version "5.1.4" resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz#2f26fa5cacb75b1402e213789f6766ae5e40313c" @@ -16756,6 +17700,16 @@ postcss-merge-rules@^5.1.4: cssnano-utils "^3.1.0" postcss-selector-parser "^6.0.5" +postcss-merge-rules@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-6.0.1.tgz#39f165746404e646c0f5c510222ccde4824a86aa" + integrity sha512-a4tlmJIQo9SCjcfiCcCMg/ZCEe0XTkl/xK0XHBs955GWg9xDX3NwP9pwZ78QUOWB8/0XCjZeJn98Dae0zg6AAw== + dependencies: + browserslist "^4.21.4" + caniuse-api "^3.0.0" + cssnano-utils "^4.0.0" + postcss-selector-parser "^6.0.5" + postcss-minify-font-values@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b" @@ -16763,6 +17717,13 @@ postcss-minify-font-values@^5.1.0: dependencies: postcss-value-parser "^4.2.0" +postcss-minify-font-values@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-6.0.0.tgz#68d4a028f9fa5f61701974724b2cc9445d8e6070" + integrity sha512-zNRAVtyh5E8ndZEYXA4WS8ZYsAp798HiIQ1V2UF/C/munLp2r1UGHwf1+6JFu7hdEhJFN+W1WJQKBrtjhFgEnA== + dependencies: + postcss-value-parser "^4.2.0" + postcss-minify-gradients@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz#f1fe1b4f498134a5068240c2f25d46fcd236ba2c" @@ -16772,6 +17733,15 @@ postcss-minify-gradients@^5.1.1: cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" +postcss-minify-gradients@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-6.0.0.tgz#22b5c88cc63091dadbad34e31ff958404d51d679" + integrity sha512-wO0F6YfVAR+K1xVxF53ueZJza3L+R3E6cp0VwuXJQejnNUH0DjcAFe3JEBeTY1dLwGa0NlDWueCA1VlEfiKgAA== + dependencies: + colord "^2.9.1" + cssnano-utils "^4.0.0" + postcss-value-parser "^4.2.0" + postcss-minify-params@^5.1.4: version "5.1.4" resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz#c06a6c787128b3208b38c9364cfc40c8aa5d7352" @@ -16781,6 +17751,15 @@ postcss-minify-params@^5.1.4: cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" +postcss-minify-params@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-6.0.0.tgz#2b3a85a9e3b990d7a16866f430f5fd1d5961b539" + integrity sha512-Fz/wMQDveiS0n5JPcvsMeyNXOIMrwF88n7196puSuQSWSa+/Ofc1gDOSY2xi8+A4PqB5dlYCKk/WfqKqsI+ReQ== + dependencies: + browserslist "^4.21.4" + cssnano-utils "^4.0.0" + postcss-value-parser "^4.2.0" + postcss-minify-selectors@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6" @@ -16788,6 +17767,13 @@ postcss-minify-selectors@^5.2.1: dependencies: postcss-selector-parser "^6.0.5" +postcss-minify-selectors@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-6.0.0.tgz#5046c5e8680a586e5a0cad52cc9aa36d6be5bda2" + integrity sha512-ec/q9JNCOC2CRDNnypipGfOhbYPuUkewGwLnbv6omue/PSASbHSU7s6uSQ0tcFRVv731oMIx8k0SP4ZX6be/0g== + dependencies: + postcss-selector-parser "^6.0.5" + postcss-modules-extract-imports@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" @@ -16854,6 +17840,11 @@ postcss-normalize-charset@^5.1.0: resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg== +postcss-normalize-charset@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-6.0.0.tgz#36cc12457259064969fb96f84df491652a4b0975" + integrity sha512-cqundwChbu8yO/gSWkuFDmKrCZ2vJzDAocheT2JTd0sFNA4HMGoKMfbk2B+J0OmO0t5GUkiAkSM5yF2rSLUjgQ== + postcss-normalize-display-values@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8" @@ -16861,6 +17852,13 @@ postcss-normalize-display-values@^5.1.0: dependencies: postcss-value-parser "^4.2.0" +postcss-normalize-display-values@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.0.tgz#8d2961415078644d8c6bbbdaf9a2fdd60f546cd4" + integrity sha512-Qyt5kMrvy7dJRO3OjF7zkotGfuYALETZE+4lk66sziWSPzlBEt7FrUshV6VLECkI4EN8Z863O6Nci4NXQGNzYw== + dependencies: + postcss-value-parser "^4.2.0" + postcss-normalize-positions@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz#ef97279d894087b59325b45c47f1e863daefbb92" @@ -16868,6 +17866,13 @@ postcss-normalize-positions@^5.1.1: dependencies: postcss-value-parser "^4.2.0" +postcss-normalize-positions@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-6.0.0.tgz#25b96df99a69f8925f730eaee0be74416865e301" + integrity sha512-mPCzhSV8+30FZyWhxi6UoVRYd3ZBJgTRly4hOkaSifo0H+pjDYcii/aVT4YE6QpOil15a5uiv6ftnY3rm0igPg== + dependencies: + postcss-value-parser "^4.2.0" + postcss-normalize-repeat-style@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz#e9eb96805204f4766df66fd09ed2e13545420fb2" @@ -16875,6 +17880,13 @@ postcss-normalize-repeat-style@^5.1.1: dependencies: postcss-value-parser "^4.2.0" +postcss-normalize-repeat-style@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.0.tgz#ddf30ad8762feb5b1eb97f39f251acd7b8353299" + integrity sha512-50W5JWEBiOOAez2AKBh4kRFm2uhrT3O1Uwdxz7k24aKtbD83vqmcVG7zoIwo6xI2FZ/HDlbrCopXhLeTpQib1A== + dependencies: + postcss-value-parser "^4.2.0" + postcss-normalize-string@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228" @@ -16882,6 +17894,13 @@ postcss-normalize-string@^5.1.0: dependencies: postcss-value-parser "^4.2.0" +postcss-normalize-string@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-6.0.0.tgz#948282647a51e409d69dde7910f0ac2ff97cb5d8" + integrity sha512-KWkIB7TrPOiqb8ZZz6homet2KWKJwIlysF5ICPZrXAylGe2hzX/HSf4NTX2rRPJMAtlRsj/yfkrWGavFuB+c0w== + dependencies: + postcss-value-parser "^4.2.0" + postcss-normalize-timing-functions@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb" @@ -16889,6 +17908,13 @@ postcss-normalize-timing-functions@^5.1.0: dependencies: postcss-value-parser "^4.2.0" +postcss-normalize-timing-functions@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.0.tgz#5f13e650b8c43351989fc5de694525cc2539841c" + integrity sha512-tpIXWciXBp5CiFs8sem90IWlw76FV4oi6QEWfQwyeREVwUy39VSeSqjAT7X0Qw650yAimYW5gkl2Gd871N5SQg== + dependencies: + postcss-value-parser "^4.2.0" + postcss-normalize-unicode@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz#f67297fca3fea7f17e0d2caa40769afc487aa030" @@ -16897,6 +17923,14 @@ postcss-normalize-unicode@^5.1.1: browserslist "^4.21.4" postcss-value-parser "^4.2.0" +postcss-normalize-unicode@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.0.tgz#741b3310f874616bdcf07764f5503695d3604730" + integrity sha512-ui5crYkb5ubEUDugDc786L/Me+DXp2dLg3fVJbqyAl0VPkAeALyAijF2zOsnZyaS1HyfPuMH0DwyY18VMFVNkg== + dependencies: + browserslist "^4.21.4" + postcss-value-parser "^4.2.0" + postcss-normalize-url@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc" @@ -16905,6 +17939,13 @@ postcss-normalize-url@^5.1.0: normalize-url "^6.0.1" postcss-value-parser "^4.2.0" +postcss-normalize-url@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-6.0.0.tgz#d0a31e962a16401fb7deb7754b397a323fb650b4" + integrity sha512-98mvh2QzIPbb02YDIrYvAg4OUzGH7s1ZgHlD3fIdTHLgPLRpv1ZTKJDnSAKr4Rt21ZQFzwhGMXxpXlfrUBKFHw== + dependencies: + postcss-value-parser "^4.2.0" + postcss-normalize-whitespace@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz#08a1a0d1ffa17a7cc6efe1e6c9da969cc4493cfa" @@ -16912,6 +17953,13 @@ postcss-normalize-whitespace@^5.1.1: dependencies: postcss-value-parser "^4.2.0" +postcss-normalize-whitespace@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.0.tgz#accb961caa42e25ca4179b60855b79b1f7129d4d" + integrity sha512-7cfE1AyLiK0+ZBG6FmLziJzqQCpTQY+8XjMhMAz8WSBSCsCNNUKujgIgjCAmDT3cJ+3zjTXFkoD15ZPsckArVw== + dependencies: + postcss-value-parser "^4.2.0" + postcss-ordered-values@^5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz#b6fd2bd10f937b23d86bc829c69e7732ce76ea38" @@ -16920,6 +17968,14 @@ postcss-ordered-values@^5.1.3: cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" +postcss-ordered-values@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-6.0.0.tgz#374704cdff25560d44061d17ba3c6308837a3218" + integrity sha512-K36XzUDpvfG/nWkjs6d1hRBydeIxGpKS2+n+ywlKPzx1nMYDYpoGbcjhj5AwVYJK1qV2/SDoDEnHzlPD6s3nMg== + dependencies: + cssnano-utils "^4.0.0" + postcss-value-parser "^4.2.0" + postcss-reduce-initial@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz#798cd77b3e033eae7105c18c9d371d989e1382d6" @@ -16928,6 +17984,14 @@ postcss-reduce-initial@^5.1.2: browserslist "^4.21.4" caniuse-api "^3.0.0" +postcss-reduce-initial@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz#7d16e83e60e27e2fa42f56ec0b426f1da332eca7" + integrity sha512-s2UOnidpVuXu6JiiI5U+fV2jamAw5YNA9Fdi/GRK0zLDLCfXmSGqQtzpUPtfN66RtCbb9fFHoyZdQaxOB3WxVA== + dependencies: + browserslist "^4.21.4" + caniuse-api "^3.0.0" + postcss-reduce-transforms@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9" @@ -16935,7 +17999,14 @@ postcss-reduce-transforms@^5.1.0: dependencies: postcss-value-parser "^4.2.0" -postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: +postcss-reduce-transforms@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.0.tgz#28ff2601a6d9b96a2f039b3501526e1f4d584a46" + integrity sha512-FQ9f6xM1homnuy1wLe9lP1wujzxnwt1EwiigtWwuyf8FsqqXUDUp2Ulxf9A5yjlUOTdCJO6lonYjg1mgqIIi2w== + dependencies: + postcss-value-parser "^4.2.0" + +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: version "6.0.13" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b" integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== @@ -16951,6 +18022,14 @@ postcss-svgo@^5.1.0: postcss-value-parser "^4.2.0" svgo "^2.7.0" +postcss-svgo@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-6.0.0.tgz#7b18742d38d4505a0455bbe70d52b49f00eaf69d" + integrity sha512-r9zvj/wGAoAIodn84dR/kFqwhINp5YsJkLoujybWG59grR/IHx+uQ2Zo+IcOwM0jskfYX3R0mo+1Kip1VSNcvw== + dependencies: + postcss-value-parser "^4.2.0" + svgo "^3.0.2" + postcss-unique-selectors@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz#a9f273d1eacd09e9aa6088f4b0507b18b1b541b6" @@ -16958,6 +18037,13 @@ postcss-unique-selectors@^5.1.1: dependencies: postcss-selector-parser "^6.0.5" +postcss-unique-selectors@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-6.0.0.tgz#c94e9b0f7bffb1203894e42294b5a1b3fb34fbe1" + integrity sha512-EPQzpZNxOxP7777t73RQpZE5e9TrnCrkvp7AH7a0l89JmZiPnS82y216JowHXwpBCQitfyxrof9TK3rYbi7/Yw== + dependencies: + postcss-selector-parser "^6.0.5" + postcss-value-parser@^3.3.0: version "3.3.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" @@ -16985,6 +18071,15 @@ postcss@^8.2.15, postcss@^8.3.5, postcss@^8.4.21: picocolors "^1.0.0" source-map-js "^1.0.2" +postcss@^8.4.24: + version "8.4.29" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.29.tgz#33bc121cf3b3688d4ddef50be869b2a54185a1dd" + integrity sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + prebuild-install@^7.0.0, prebuild-install@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.1.tgz#de97d5b34a70a0c81334fd24641f2a1702352e45" @@ -17583,7 +18678,7 @@ react-merge-refs@^1.0.0: resolved "https://registry.yarnpkg.com/react-merge-refs/-/react-merge-refs-1.1.0.tgz#73d88b892c6c68cbb7a66e0800faa374f4c38b06" integrity sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ== -react-refresh-typescript@^2.0.2, react-refresh-typescript@^2.0.3: +react-refresh-typescript@^2.0.2: version "2.0.9" resolved "https://registry.yarnpkg.com/react-refresh-typescript/-/react-refresh-typescript-2.0.9.tgz#f8a86efcb34f8d717100230564b9b57477d74b10" integrity sha512-chAnOO4vpxm/3WkgOVmti+eN8yUtkJzeGkOigV6UA9eDFz12W34e/SsYe2H5+RwYJ3+sfSZkVbiXcG1chEBxlg== @@ -17879,6 +18974,13 @@ rechoir@^0.7.0: dependencies: resolve "^1.9.0" +rechoir@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" + integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== + dependencies: + resolve "^1.20.0" + redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" @@ -17927,6 +19029,13 @@ regenerator-transform@^0.15.1: dependencies: "@babel/runtime" "^7.8.4" +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== + dependencies: + "@babel/runtime" "^7.8.4" + regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -18473,7 +19582,7 @@ schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: ajv "^6.12.5" ajv-keywords "^3.5.2" -schema-utils@^4.0.0: +schema-utils@^4.0.0, schema-utils@^4.0.1: version "4.2.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== @@ -18526,6 +19635,11 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +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: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" @@ -18824,6 +19938,11 @@ slash@^2.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" @@ -18911,7 +20030,7 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -source-map-js@^1.0.2: +source-map-js@^1.0.1, source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== @@ -19381,7 +20500,7 @@ style-loader@^2.0.0: loader-utils "^2.0.0" schema-utils "^3.0.0" -style-loader@^3.3.1: +style-loader@^3.3.1, style-loader@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.3.tgz#bba8daac19930169c0c9c96706749a597ae3acff" integrity sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw== @@ -19408,6 +20527,14 @@ stylehacks@^5.1.1: browserslist "^4.21.4" postcss-selector-parser "^6.0.4" +stylehacks@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-6.0.0.tgz#9fdd7c217660dae0f62e14d51c89f6c01b3cb738" + integrity sha512-+UT589qhHPwz6mTlCLSt/vMNTJx8dopeJlZAlBMJPWA3ORqu6wmQY7FBXf+qD+FsqoBJODyqNxOUP3jdntFRdw== + dependencies: + browserslist "^4.21.4" + postcss-selector-parser "^6.0.4" + stylis@4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" @@ -19470,6 +20597,18 @@ svgo@^2.7.0, svgo@^2.8.0: picocolors "^1.0.0" stable "^0.1.8" +svgo@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.0.2.tgz#5e99eeea42c68ee0dc46aa16da093838c262fe0a" + integrity sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ== + dependencies: + "@trysound/sax" "0.2.0" + commander "^7.2.0" + css-select "^5.1.0" + css-tree "^2.2.1" + csso "^5.0.5" + picocolors "^1.0.0" + symbol-observable@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-2.0.3.tgz#5b521d3d07a43c351055fa43b8355b62d33fd16a" @@ -19701,6 +20840,16 @@ thread-loader@^3.0.4: neo-async "^2.6.2" schema-utils "^3.0.0" +thread-loader@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/thread-loader/-/thread-loader-4.0.2.tgz#f7b4484beab1f928818d8ecd96ef20c618d1fadc" + integrity sha512-UOk/KBydsQjh4Ja5kocxDUzhv11KYptHN/h8gdSwo6/MBkYrWqQua6K2qwlpXnCXS9c/uLs8F/JF8rpveF0+fA== + dependencies: + json-parse-better-errors "^1.0.2" + loader-runner "^4.1.0" + neo-async "^2.6.2" + schema-utils "^4.0.1" + throat@^6.0.1: version "6.0.2" resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.2.tgz#51a3fbb5e11ae72e2cf74861ed5c8020f89f29fe" @@ -19936,7 +21085,7 @@ ts-jest@^29.1.0: semver "^7.5.3" yargs-parser "^21.0.1" -ts-loader@^9.4.2: +ts-loader@^9.4.2, ts-loader@^9.4.4: version "9.4.4" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.4.4.tgz#6ceaf4d58dcc6979f84125335904920884b7cee4" integrity sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w== @@ -20002,6 +21151,15 @@ tsconfig-paths-webpack-plugin@^3.5.2: enhanced-resolve "^5.7.0" tsconfig-paths "^3.9.0" +tsconfig-paths-webpack-plugin@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz#3c6892c5e7319c146eee1e7302ed9e6f2be4f763" + integrity sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA== + dependencies: + chalk "^4.1.0" + enhanced-resolve "^5.7.0" + tsconfig-paths "^4.1.2" + tsconfig-paths@^3.14.1, tsconfig-paths@^3.5.0, tsconfig-paths@^3.9.0: version "3.14.2" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" @@ -20882,6 +22040,25 @@ webpack-cli@^4.8.0: rechoir "^0.7.0" webpack-merge "^5.7.3" +webpack-cli@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" + integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^2.1.1" + "@webpack-cli/info" "^2.0.2" + "@webpack-cli/serve" "^2.0.5" + colorette "^2.0.14" + commander "^10.0.1" + cross-spawn "^7.0.3" + envinfo "^7.7.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^3.1.1" + rechoir "^0.8.0" + webpack-merge "^5.7.3" + webpack-dev-middleware@^3.7.3: version "3.7.3" resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" @@ -20916,7 +22093,7 @@ webpack-dev-middleware@^5.3.1: range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-dev-server@^4.5.0: +webpack-dev-server@^4.15.1, webpack-dev-server@^4.5.0: version "4.15.1" resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz#8944b29c12760b3a45bdaa70799b17cb91b03df7" integrity sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA== @@ -20981,7 +22158,7 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-merge@^5.7.3, webpack-merge@^5.8.0: +webpack-merge@^5.7.3, webpack-merge@^5.8.0, webpack-merge@^5.9.0: version "5.9.0" resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.9.0.tgz#dc160a1c4cf512ceca515cc231669e9ddb133826" integrity sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg== @@ -21073,6 +22250,36 @@ webpack@4: watchpack "^2.4.0" webpack-sources "^3.2.3" +webpack@^5.88.2: + version "5.88.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.88.2.tgz#f62b4b842f1c6ff580f3fcb2ed4f0b579f4c210e" + integrity sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^1.0.0" + "@webassemblyjs/ast" "^1.11.5" + "@webassemblyjs/wasm-edit" "^1.11.5" + "@webassemblyjs/wasm-parser" "^1.11.5" + acorn "^8.7.1" + acorn-import-assertions "^1.9.0" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.15.0" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.2.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.7" + watchpack "^2.4.0" + webpack-sources "^3.2.3" + websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" @@ -21476,6 +22683,11 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +yocto-queue@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" + integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== + yup@^0.32.9: version "0.32.11" resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.11.tgz#d67fb83eefa4698607982e63f7ca4c5ed3cf18c5"