diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index b72be4c0..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,382 +0,0 @@ -version: 2.1 - -orbs: - tokenbridge-orb: - commands: - install-chrome: - steps: - - run: - name: Update dpkg - command: | - sudo apt-get clean - sudo apt-get update - sudo apt-get install dpkg - - run: - name: Install Chrome - command: | - wget -O chrome.deb https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_77.0.3865.120-1_amd64.deb - sudo dpkg -i chrome.deb - install-node: - steps: - - run: - name: Install Node - command: | - export NVM_DIR="/opt/circleci/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - - nvm install 10.16.3 && nvm alias default 10.16.3 - - echo 'export NVM_DIR="/opt/circleci/.nvm"' >> $BASH_ENV - echo ' [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV - install-yarn: - steps: - - run: - name: Install Yarn - command: | - curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - - echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list - sudo apt-get update && sudo apt-get -y install yarn - wait-for-oracle: - parameters: - redis-key: - type: string - steps: - - run: - name: Install redis tools - command: sudo apt-get install -y redis-tools - - run: - name: Wait for the Oracle to start - command: | - set +e - i=0 - while [[ $(redis-cli GET << parameters.redis-key >> ) ]]; do - ((i++)) - if [ "$i" -gt 30 ] - then - exit -1 - fi - - echo "Sleeping..." - sleep 3 - done - init-repo: - steps: - - checkout - - run: git submodule update --init - executors: - docker-node: - docker: - - image: circleci/node:10.15 - machine-with-dlc: - machine: - image: ubuntu-1604:202007-01 - docker_layer_caching: true - classic-machine-without-dlc: - machine: - image: circleci/classic:latest - machine-without-dlc: - machine: - image: ubuntu-1604:202007-01 - -jobs: - initialize: - executor: tokenbridge-orb/docker-node - steps: - - tokenbridge-orb/init-repo - - restore_cache: - name: Restore Yarn Package Cache - keys: - - yarn-{{ checksum "package.json" }}-{{ checksum "yarn.lock" }} - - run: git submodule status > submodule.status - - restore_cache: - name: Restore contracts submodule with compiled contracts - keys: - - contracts-{{ checksum "submodule.status" }} - - run: yarn install --frozen-lockfile - - save_cache: - name: Save Yarn Package Cache - key: yarn-{{ checksum "package.json" }}-{{ checksum "yarn.lock" }} - paths: - - ~/.cache/yarn - - run: touch install_deploy.log; test -d contracts/build/contracts || yarn install:deploy &> install_deploy.log - - store_artifacts: - path: install_deploy.log - - run: test -d contracts/build/contracts || yarn compile:contracts - - save_cache: - name: Save contracts submodule with compiled contracts - key: contracts-{{ checksum "submodule.status" }} - paths: - - contracts - - save_cache: - name: Save initialized project for subsequent jobs - key: initialize-{{ .Environment.CIRCLE_SHA1 }} - paths: - - ~/project - initialize-root: - executor: tokenbridge-orb/docker-node - steps: - - checkout - - run: sudo su - -c 'export CI=true && cd /home/circleci/project && yarn initialize && yarn test' - build: - executor: tokenbridge-orb/docker-node - steps: - - restore_cache: - key: initialize-{{ .Environment.CIRCLE_SHA1 }} - - run: yarn run build - lint: - executor: tokenbridge-orb/docker-node - steps: - - restore_cache: - key: initialize-{{ .Environment.CIRCLE_SHA1 }} - - run: yarn run lint - test: - executor: tokenbridge-orb/docker-node - steps: - - restore_cache: - key: initialize-{{ .Environment.CIRCLE_SHA1 }} - - run: yarn run test - build-e2e-images: - executor: tokenbridge-orb/machine-without-dlc - steps: - - tokenbridge-orb/init-repo - - run: - command: | - docker login -u ${DOCKER_LOGIN} -p ${DOCKER_PASSWORD} - cd e2e-commons - docker-compose build oracle monitor ui alm e2e molecule_runner - docker-compose push oracle monitor ui alm e2e molecule_runner - oracle-e2e: - executor: tokenbridge-orb/machine-without-dlc - steps: - - tokenbridge-orb/init-repo - - run: ./oracle-e2e/run-tests.sh - ui-e2e: - executor: tokenbridge-orb/machine-without-dlc - steps: - - tokenbridge-orb/install-node - - tokenbridge-orb/install-yarn - - tokenbridge-orb/install-chrome - - restore_cache: - key: initialize-{{ .Environment.CIRCLE_SHA1 }} - - run: yarn run ui-e2e - monitor-e2e: - executor: tokenbridge-orb/machine-without-dlc - steps: - - tokenbridge-orb/init-repo - - run: ./monitor-e2e/run-tests.sh - alm-e2e: - executor: tokenbridge-orb/machine-without-dlc - steps: - - tokenbridge-orb/install-node - - tokenbridge-orb/install-yarn - - restore_cache: - key: initialize-{{ .Environment.CIRCLE_SHA1 }} - - run: yarn run alm-e2e - cover: - executor: tokenbridge-orb/docker-node - steps: - - restore_cache: - key: initialize-{{ .Environment.CIRCLE_SHA1 }} - - run: yarn workspace ui run coverage - - run: yarn workspace ui run coveralls - deployment-oracle: - executor: tokenbridge-orb/machine-without-dlc - steps: - - tokenbridge-orb/init-repo - - run: - name: Run the scenario - command: deployment-e2e/molecule.sh oracle - no_output_timeout: 40m - deployment-ui: - executor: tokenbridge-orb/machine-without-dlc - steps: - - tokenbridge-orb/init-repo - - run: - name: Run the scenario - command: deployment-e2e/molecule.sh ui - no_output_timeout: 40m - deployment-monitor: - executor: tokenbridge-orb/machine-without-dlc - steps: - - tokenbridge-orb/init-repo - - run: - name: Run the scenario - command: deployment-e2e/molecule.sh monitor - no_output_timeout: 40m - deployment-repo: - executor: tokenbridge-orb/machine-without-dlc - steps: - - tokenbridge-orb/init-repo - - run: - name: Run the scenario - command: deployment-e2e/molecule.sh repo - no_output_timeout: 40m - deployment-multiple: - executor: tokenbridge-orb/machine-without-dlc - steps: - - tokenbridge-orb/init-repo - - run: - name: Run the scenario - command: deployment-e2e/molecule.sh multiple - no_output_timeout: 40m - ultimate: - executor: tokenbridge-orb/classic-machine-without-dlc - parameters: - scenario-name: - description: "Molecule scenario name used to create the infrastructure" - type: string - redis-key: - description: "Redis key checked for non-emptiness to assert if Oracle is running" - type: string - ui-e2e-grep: - description: "Mocha grep string used to run ui-e2e tests specific to given type of bridge" - default: '' - type: string - oracle-e2e-script: - description: "Yarn script string used to run oracle-e2e tests specific to given type of bridge" - default: '' - type: string - steps: - - tokenbridge-orb/install-node - - tokenbridge-orb/install-chrome - - tokenbridge-orb/install-yarn - - restore_cache: - key: initialize-{{ .Environment.CIRCLE_SHA1 }} - - run: - name: Prepare the infrastructure - command: e2e-commons/up.sh deploy << parameters.scenario-name >> blocks - no_output_timeout: 50m - - tokenbridge-orb/wait-for-oracle: - redis-key: << parameters.redis-key >> - - when: - condition: << parameters.ui-e2e-grep >> - steps: - - run: - name: Run the ui-e2e tests - command: | - nvm use default; - cd ui-e2e; yarn mocha -g "<< parameters.ui-e2e-grep >>" -b ./test.js - - when: - condition: << parameters.oracle-e2e-script >> - steps: - - run: - name: Run the oracle-e2e tests - command: cd e2e-commons && docker-compose run e2e yarn workspace oracle-e2e run << parameters.oracle-e2e-script >> -workflows: - tokenbridge: - jobs: - - initialize - - initialize-root: - filters: - branches: - only: master - - build: - requires: - - initialize - - lint: - requires: - - initialize - - test: - requires: - - initialize - - cover: - requires: - - initialize - filters: - branches: - only: master - - build-e2e-images - - oracle-e2e: - requires: - - build-e2e-images - - ui-e2e: - requires: - - build-e2e-images - - initialize - - monitor-e2e: - requires: - - build-e2e-images - - alm-e2e: - requires: - - build-e2e-images - - initialize - - deployment-oracle: - requires: - - build-e2e-images - - deployment-ui: - requires: - - build-e2e-images - - deployment-monitor: - requires: - - build-e2e-images - - deployment-repo: - requires: - - build-e2e-images - - deployment-multiple: - requires: - - build-e2e-images - - ultimate: - requires: - - build-e2e-images - - initialize - filters: - branches: - only: - - master - - develop - name: "ultimate: native to erc" - scenario-name: native-to-erc - redis-key: native-erc-collected-signatures:lastProcessedBlock - ui-e2e-grep: "NATIVE TO ERC" - - ultimate: - requires: - - build-e2e-images - - initialize - filters: - branches: - only: - - master - - develop - name: "ultimate: erc to native" - scenario-name: erc-to-native - redis-key: erc-native-collected-signatures:lastProcessedBlock - ui-e2e-grep: "ERC TO NATIVE" - - ultimate: - requires: - - build-e2e-images - - initialize - filters: - branches: - only: - - master - - develop - name: "ultimate: erc to erc" - scenario-name: erc-to-erc - redis-key: erc-erc-collected-signatures:lastProcessedBlock - ui-e2e-grep: "ERC TO ERC" - - ultimate: - requires: - - build-e2e-images - - initialize - filters: - branches: - only: - - master - - develop - name: "ultimate: amb" - scenario-name: amb - redis-key: amb-collected-signatures:lastProcessedBlock - oracle-e2e-script: "amb" - - ultimate: - requires: - - build-e2e-images - - initialize - filters: - branches: - only: - - master - - develop - name: "ultimate: amb stake erc to erc" - scenario-name: ultimate-amb-stake-erc-to-erc - redis-key: amb-collected-signatures:lastProcessedBlock - ui-e2e-grep: "AMB-STAKE-ERC-TO-ERC" diff --git a/.dockerignore b/.dockerignore index 8e46cde6..b4795279 100644 --- a/.dockerignore +++ b/.dockerignore @@ -11,6 +11,9 @@ contracts/test contracts/build oracle/test +monitor/test +monitor/responses +commons/test oracle/**/*.png oracle/**/*.jpg audit diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..8927c620 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,231 @@ +name: tokenbridge + +on: [push] + +env: + DOCKER_REGISTRY: docker.pkg.github.com + DOCKER_REPO: poanetwork/tokenbridge + DOCKER_IMAGE_BASE: docker.pkg.github.com/poanetwork/tokenbridge + +jobs: + initialize: + runs-on: ubuntu-latest + outputs: + cache_key: ${{ steps.get_cache_key.outputs.cache_key }} + steps: + - uses: actions/setup-node@v1 + with: + node-version: 10 + - uses: actions/checkout@v2 + with: + submodules: true + - run: git submodule status > submodule.status + - id: get_cache_key + run: echo "::set-output name=cache_key::cache-repo-${{ hashFiles('yarn.lock', 'package.json', 'submodule.status') }}" + - uses: actions/cache@v2 + id: cache-repo + with: + path: | + **/node_modules + contracts/build + key: ${{ steps.get_cache_key.outputs.cache_key }} + - if: ${{ !steps.cache-repo.outputs.cache-hit }} + run: | + yarn install --frozen-lockfile + yarn run install:deploy + yarn run compile:contracts + validate: + runs-on: ubuntu-latest + needs: + - initialize + strategy: + fail-fast: false + matrix: + task: [build, lint, test] + steps: + - uses: actions/setup-node@v1 + with: + node-version: 10 + - uses: actions/checkout@v2 + with: + submodules: true + - uses: actions/cache@v2 + id: cache-repo + with: + path: | + **/node_modules + contracts/build + key: ${{ needs.initialize.outputs.cache_key }} + - run: ${{ steps.cache-repo.outputs.cache-hit }} && yarn run ${{ matrix.task }} + ui-coverage: + runs-on: ubuntu-latest + needs: + - initialize + if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags') + steps: + - uses: actions/setup-node@v1 + with: + node-version: 10 + - uses: actions/checkout@v2 + with: + submodules: true + - uses: actions/cache@v2 + id: cache-repo + with: + path: | + **/node_modules + contracts/build + key: ${{ needs.initialize.outputs.cache_key }} + - run: ${{ steps.cache-repo.outputs.cache-hit }} && yarn workspace ui run coverage + - uses: coverallsapp/github-action@master + with: + github-token: ${{ github.token }} + path-to-lcov: ./ui/coverage/lcov.info + build-e2e-images: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - run: | + git submodule status > submodule.status + echo "::set-env name=E2E_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" + echo "::set-env name=ORACLE_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" + echo "::set-env name=MONITOR_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" + echo "::set-env name=UI_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}" + echo "::set-env name=ALM_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" + - run: | + function check_if_image_exists() { + curl -fsSlL -H 'Authorization: bearer ${{ github.token }}' "https://${DOCKER_REGISTRY}/v2/${DOCKER_REPO}/tokenbridge-e2e-$1/manifests/$2" > /dev/null + } + updated=() + if ! check_if_image_exists e2e ${E2E_TAG}; then updated+=("e2e"); fi + if ! check_if_image_exists oracle ${ORACLE_TAG}; then updated+=("oracle"); fi + if ! check_if_image_exists monitor ${MONITOR_TAG}; then updated+=("monitor"); fi + if ! check_if_image_exists ui ${UI_TAG}; then updated+=("ui"); fi + if ! check_if_image_exists alm ${ALM_TAG}; then updated+=("alm"); fi + if [ ${#updated[@]} -gt 0 ]; then + echo "Updated services: ${updated[@]}" + cd e2e-commons + docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }} + docker-compose build ${updated[@]} + docker-compose push ${updated[@]} + else + echo "Nothing relevant was changed in the source" + fi + build-molecule-runner: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - run: echo "::set-env name=MOLECULE_RUNNER_TAG::${{ hashFiles('./deployment-e2e/Dockerfile') }}" + - run: | + function check_if_image_exists() { + curl -fsSlL -H 'Authorization: bearer ${{ github.token }}' "https://${DOCKER_REGISTRY}/v2/${DOCKER_REPO}/tokenbridge-e2e-$1/manifests/$2" > /dev/null + } + if check_if_image_exists molecule_runner ${MOLECULE_RUNNER_TAG}; then + echo "Image already exists" + else + cd e2e-commons + docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }} + docker-compose build molecule_runner + docker-compose push molecule_runner + fi + e2e: + runs-on: ubuntu-latest + needs: + - initialize + - build-e2e-images + strategy: + fail-fast: false + matrix: + task: [oracle-e2e, monitor-e2e, alm-e2e, 'ui-e2e:ci'] + include: + - task: alm-e2e + use-cache: true + - task: 'ui-e2e:ci' + use-cache: true + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - run: | + git submodule status > submodule.status + echo "::set-env name=E2E_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" + echo "::set-env name=ORACLE_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" + echo "::set-env name=MONITOR_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" + echo "::set-env name=UI_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}" + echo "::set-env name=ALM_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" + - if: ${{ matrix.use-cache }} + uses: actions/cache@v2 + id: cache-repo + with: + path: | + **/node_modules + contracts/build + key: ${{ needs.initialize.outputs.cache_key }} + - run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }} + - run: ${{ !matrix.use-cache || steps.cache-repo.outputs.cache-hit }} && yarn run ${{ matrix.task }} + deployment: + runs-on: ubuntu-latest + needs: + - build-molecule-runner + strategy: + fail-fast: false + matrix: + task: [oracle, ui, monitor, multiple, repo] + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - run: echo "::set-env name=MOLECULE_RUNNER_TAG::${{ hashFiles('./deployment-e2e/Dockerfile') }}" + - run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }} + - run: deployment-e2e/molecule.sh ${{ matrix.task }} + ultimate: + runs-on: ubuntu-latest + needs: + - initialize + - build-e2e-images + if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/tags') + strategy: + fail-fast: false + matrix: + task: [amb, erc-to-erc, erc-to-native, native-to-erc, amb-stake-erc-to-erc] + include: + - task: erc-to-erc + ui-e2e-grep: 'ERC TO ERC' + - task: erc-to-native + ui-e2e-grep: 'ERC TO NATIVE' + - task: native-to-erc + ui-e2e-grep: 'NATIVE TO ERC' + - task: amb-stake-erc-to-erc + ui-e2e-grep: 'AMB-STAKE-ERC-TO-ERC' + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - run: | + git submodule status > submodule.status + echo "::set-env name=E2E_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'Dockerfile.e2e', 'commons', 'oracle-e2e', 'monitor-e2e') }}" + echo "::set-env name=ORACLE_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'oracle') }}" + echo "::set-env name=MONITOR_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'monitor') }}" + echo "::set-env name=UI_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'ui') }}" + echo "::set-env name=ALM_TAG::${{ hashFiles('yarn.lock', 'package.json', 'submodule.status', 'commons', 'alm') }}" + echo "::set-env name=MOLECULE_RUNNER_TAG::${{ hashFiles('./deployment-e2e/Dockerfile') }}" + - uses: actions/cache@v2 + id: cache-repo + with: + path: | + **/node_modules + contracts/build + key: ${{ needs.initialize.outputs.cache_key }} + - run: docker login ${DOCKER_REGISTRY} -u ${{ github.actor }} -p ${{ github.token }} + - run: ${{ steps.cache-repo.outputs.cache-hit }} && e2e-commons/up.sh deploy blocks + - run: docker-compose -f ./e2e-commons/docker-compose.yml pull oracle + - run: deployment-e2e/molecule.sh ultimate-${{ matrix.task }} + - run: sudo chown -R $USER:docker /var/run/docker.sock + - if: ${{ matrix.ui-e2e-grep }} + run: cd ui-e2e && xvfb-run yarn mocha -g "${{ matrix.ui-e2e-grep }}" -b ./test.js + - if: ${{ !matrix.ui-e2e-grep }} + run: docker-compose -f ./e2e-commons/docker-compose.yml run e2e yarn workspace oracle-e2e run ${{ matrix.task }} diff --git a/Dockerfile.e2e b/Dockerfile.e2e index 4f0e1db3..cad4d3a7 100644 --- a/Dockerfile.e2e +++ b/Dockerfile.e2e @@ -1,4 +1,4 @@ -FROM node:8 as contracts +FROM node:10 as contracts WORKDIR /mono @@ -11,11 +11,12 @@ COPY ./contracts/truffle-config.js ./ COPY ./contracts/contracts ./contracts RUN npm run compile -FROM node:8 +FROM node:10 WORKDIR /mono COPY package.json . COPY --from=contracts /mono/contracts/build ./contracts/build +COPY commons/package.json ./commons/ COPY oracle-e2e/package.json ./oracle-e2e/ COPY monitor-e2e/package.json ./monitor-e2e/ diff --git a/README.md b/README.md index e6fbe9ee..c2990bd3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![CircleCI](https://circleci.com/gh/poanetwork/tokenbridge.svg?style=svg)](https://circleci.com/gh/poanetwork/tokenbridge) +![tokenbridge](https://github.com/poanetwork/tokenbridge/workflows/tokenbridge/badge.svg?branch=master) [![Gitter](https://badges.gitter.im/poanetwork/poa-bridge.svg)](https://gitter.im/poanetwork/poa-bridge?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![License: LGPL v3.0](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0) @@ -110,4 +110,4 @@ This project is licensed under the GNU Lesser General Public License v3.0. See t ## References -* [TokenBridge Documentation](http://www.tokenbridge.net/) +* [TokenBridge Documentation](https://docs.tokenbridge.net/) diff --git a/alm-e2e/run-tests.sh b/alm-e2e/run-tests.sh old mode 100644 new mode 100755 diff --git a/alm/Dockerfile b/alm/Dockerfile index 7fdc124b..66c11784 100644 --- a/alm/Dockerfile +++ b/alm/Dockerfile @@ -1,4 +1,4 @@ -FROM node:8 as contracts +FROM node:10 as contracts WORKDIR /mono diff --git a/alm/src/utils/__tests__/getConfirmationsForTx.test.ts b/alm/src/utils/__tests__/getConfirmationsForTx.test.ts index 67aa5fa5..7667f25a 100644 --- a/alm/src/utils/__tests__/getConfirmationsForTx.test.ts +++ b/alm/src/utils/__tests__/getConfirmationsForTx.test.ts @@ -351,7 +351,7 @@ describe('getConfirmationsForTx', () => { { validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS }, { validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS }, { validator: validator3, status: VALIDATOR_CONFIRMATION_STATUS.FAILED, txHash: '0x123', timestamp: 123 }, - { validator: validator4, status: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED } + { validator: validator4, status: VALIDATOR_CONFIRMATION_STATUS.NOT_REQUIRED } ]) ) expect(setResult.mock.calls[1][0]).toEqual( diff --git a/deployment-e2e/README.md b/deployment-e2e/README.md index a01f47f0..8c36faf7 100644 --- a/deployment-e2e/README.md +++ b/deployment-e2e/README.md @@ -13,7 +13,7 @@ git push Alternatively, if there are no changes except the playbooks, you can use the `master` branch: ``` -CIRCLE_BRANCH=master ./molecule.sh +./molecule.sh ``` In this case `master` branch will be used as a codebase for Monitor, UI, Oracle and Contracts deployed by your local playbook. @@ -21,7 +21,7 @@ In this case `master` branch will be used as a codebase for Monitor, UI, Oracle ## Run the tests ``` -CIRCLE_BRANCH=master ./molecule.sh +./molecule.sh ``` Available scenarios: diff --git a/deployment-e2e/molecule.sh b/deployment-e2e/molecule.sh index 18389c18..021feead 100755 --- a/deployment-e2e/molecule.sh +++ b/deployment-e2e/molecule.sh @@ -2,7 +2,11 @@ cd ./e2e-commons set -e # exit when any command fails -docker-compose pull molecule_runner +if [ -z "$CI" ]; then + docker-compose build molecule_runner +else + docker-compose pull molecule_runner +fi docker network create --driver bridge ultimate || true while [ "$1" != "" ]; do docker-compose run molecule_runner /bin/bash -c "molecule test --scenario-name $1" diff --git a/deployment-e2e/molecule/ultimate-commons/oracle-docker-compose.yml b/deployment-e2e/molecule/ultimate-commons/oracle-docker-compose.yml index 23bc83f1..e36b57db 100644 --- a/deployment-e2e/molecule/ultimate-commons/oracle-docker-compose.yml +++ b/deployment-e2e/molecule/ultimate-commons/oracle-docker-compose.yml @@ -6,12 +6,10 @@ - name: stop the service shell: service poabridge stop - - name: Build current oracle image - shell: docker build -t oracle:ultimate-testing --file oracle/Dockerfile . + - name: ReTag current oracle image + shell: docker tag $(docker images --format '{{ '{{' }}.Repository{{ '}}' }}:{{ '{{' }}.Tag{{ '}}' }}' | grep -m 1 tokenbridge-e2e-oracle) oracle:ultimate-testing delegate_to: 127.0.0.1 become: false - args: - chdir: "{{ lookup('env', 'PWD') }}/.." - name: Replace oracle image replace: diff --git a/deployment/roles/common/tasks/repo.yml b/deployment/roles/common/tasks/repo.yml index 8dd4546b..4fb8dd00 100644 --- a/deployment/roles/common/tasks/repo.yml +++ b/deployment/roles/common/tasks/repo.yml @@ -12,6 +12,7 @@ copy: src: ../../../../{{ item }} dest: "{{ bridge_path }}/" + mode: '0640' with_items: - monorepo.tar.gz - contracts.tar.gz diff --git a/deployment/roles/monitor/tasks/pre_config.yml b/deployment/roles/monitor/tasks/pre_config.yml index 4ef7c155..bd50a87e 100644 --- a/deployment/roles/monitor/tasks/pre_config.yml +++ b/deployment/roles/monitor/tasks/pre_config.yml @@ -24,6 +24,8 @@ template: src: .env.j2 dest: "{{ bridge_path }}/monitor/.env" + owner: "{{ compose_service_user }}" + mode: '0640' when: skip_task != true - name: Copy docker-compose file @@ -45,3 +47,5 @@ template: src: config.env.j2 dest: "{{ bridge_path }}/monitor/configs/{{ MONITOR_BRIDGE_NAME }}.env" + owner: "{{ compose_service_user }}" + mode: '0640' diff --git a/deployment/roles/oracle/tasks/pre_config.yml b/deployment/roles/oracle/tasks/pre_config.yml index 72779cb9..7e7c501e 100644 --- a/deployment/roles/oracle/tasks/pre_config.yml +++ b/deployment/roles/oracle/tasks/pre_config.yml @@ -9,6 +9,8 @@ template: src: .env.j2 dest: "{{ bridge_path }}/oracle/.env" + owner: "{{ compose_service_user }}" + mode: '0640' - name: Copy docker-compose files copy: diff --git a/deployment/roles/ui/tasks/pre_config.yml b/deployment/roles/ui/tasks/pre_config.yml index 40497300..bc27eac5 100644 --- a/deployment/roles/ui/tasks/pre_config.yml +++ b/deployment/roles/ui/tasks/pre_config.yml @@ -3,3 +3,5 @@ template: src: .env.j2 dest: "{{ bridge_path }}/ui/.env" + owner: "{{ compose_service_user }}" + mode: '0640' diff --git a/e2e-commons/Dockerfile.ui b/e2e-commons/Dockerfile.ui index cbd415a5..8d116952 100644 --- a/e2e-commons/Dockerfile.ui +++ b/e2e-commons/Dockerfile.ui @@ -1,6 +1,6 @@ -ARG DOCKER_LOGIN -ARG CIRCLE_BRANCH -FROM ${DOCKER_LOGIN}/tokenbridge-e2e-ui:${CIRCLE_BRANCH} +ARG DOCKER_IMAGE_BASE +ARG UI_TAG +FROM ${DOCKER_IMAGE_BASE}/tokenbridge-e2e-ui:${UI_TAG} ARG DOT_ENV_PATH diff --git a/e2e-commons/build.sh b/e2e-commons/build.sh new file mode 100755 index 00000000..6f0a13e3 --- /dev/null +++ b/e2e-commons/build.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +cd $(dirname $0) +set -e # exit when any command fails + +docker-compose build e2e +while [ "$1" != "" ]; do + if [ "$1" == "oracle" ]; then + docker-compose build oracle + elif [ "$1" == "monitor" ]; then + docker-compose build monitor + elif [ "$1" == "ui" ]; then + docker-compose build ui + elif [ "$1" == "alm" ]; then + docker-compose build alm + fi + shift +done diff --git a/e2e-commons/docker-compose.yml b/e2e-commons/docker-compose.yml index 00e1660a..84939236 100644 --- a/e2e-commons/docker-compose.yml +++ b/e2e-commons/docker-compose.yml @@ -1,5 +1,4 @@ ---- -version: '3' +version: '3.8' networks: ultimate: external: true @@ -27,7 +26,7 @@ services: networks: - ultimate oracle: - image: ${DOCKER_LOGIN}/tokenbridge-e2e-oracle:${CIRCLE_BRANCH} + image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local} build: context: .. dockerfile: oracle/Dockerfile @@ -38,10 +37,7 @@ services: networks: - ultimate oracle-erc20: - image: ${DOCKER_LOGIN}/tokenbridge-e2e-oracle:${CIRCLE_BRANCH} - build: - context: .. - dockerfile: oracle/Dockerfile + image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local} env_file: ../e2e-commons/components-envs/oracle-erc20.env environment: - NODE_ENV=production @@ -49,10 +45,7 @@ services: networks: - ultimate oracle-erc20-native: - image: ${DOCKER_LOGIN}/tokenbridge-e2e-oracle:${CIRCLE_BRANCH} - build: - context: .. - dockerfile: oracle/Dockerfile + image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local} env_file: ../e2e-commons/components-envs/oracle-erc20-native.env environment: - NODE_ENV=production @@ -60,10 +53,7 @@ services: networks: - ultimate oracle-amb: - image: ${DOCKER_LOGIN}/tokenbridge-e2e-oracle:${CIRCLE_BRANCH} - build: - context: .. - dockerfile: oracle/Dockerfile + image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-oracle:${ORACLE_TAG:-local} env_file: ../e2e-commons/components-envs/oracle-amb.env environment: - NODE_ENV=production @@ -71,7 +61,7 @@ services: networks: - ultimate ui: - image: ${DOCKER_LOGIN}/tokenbridge-e2e-ui:${CIRCLE_BRANCH} + image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-ui:${UI_TAG:-local} build: context: .. dockerfile: ui/Dockerfile @@ -85,8 +75,8 @@ services: context: .. dockerfile: e2e-commons/Dockerfile.ui args: - DOCKER_LOGIN: ${DOCKER_LOGIN} - CIRCLE_BRANCH: ${CIRCLE_BRANCH} + DOCKER_IMAGE_BASE: ${DOCKER_IMAGE_BASE:-tokenbridge} + UI_TAG: ${UI_TAG:-local} DOT_ENV_PATH: e2e-commons/components-envs/ui-erc20.env command: "true" networks: @@ -96,8 +86,8 @@ services: context: .. dockerfile: e2e-commons/Dockerfile.ui args: - DOCKER_LOGIN: ${DOCKER_LOGIN} - CIRCLE_BRANCH: ${CIRCLE_BRANCH} + DOCKER_IMAGE_BASE: ${DOCKER_IMAGE_BASE:-tokenbridge} + UI_TAG: ${UI_TAG:-local} DOT_ENV_PATH: e2e-commons/components-envs/ui-erc20-native.env command: "true" networks: @@ -107,14 +97,14 @@ services: context: .. dockerfile: e2e-commons/Dockerfile.ui args: - DOCKER_LOGIN: ${DOCKER_LOGIN} - CIRCLE_BRANCH: ${CIRCLE_BRANCH} + DOCKER_IMAGE_BASE: ${DOCKER_IMAGE_BASE:-tokenbridge} + UI_TAG: ${UI_TAG:-local} DOT_ENV_PATH: e2e-commons/components-envs/ui-amb-stake-erc20-erc20.env command: "true" networks: - ultimate alm: - image: ${DOCKER_LOGIN}/tokenbridge-e2e-alm:${CIRCLE_BRANCH} + image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-alm:${ALM_TAG:-local} build: context: .. dockerfile: alm/Dockerfile @@ -124,7 +114,7 @@ services: networks: - ultimate monitor: - image: ${DOCKER_LOGIN}/tokenbridge-e2e-monitor:${CIRCLE_BRANCH} + image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local} build: context: .. dockerfile: monitor/Dockerfile @@ -135,10 +125,7 @@ services: networks: - ultimate monitor-erc20: - image: ${DOCKER_LOGIN}/tokenbridge-e2e-monitor:${CIRCLE_BRANCH} - build: - context: .. - dockerfile: monitor/Dockerfile + image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local} env_file: ../e2e-commons/components-envs/monitor-erc20.env entrypoint: yarn check-and-start ports: @@ -146,10 +133,7 @@ services: networks: - ultimate monitor-erc20-native: - image: ${DOCKER_LOGIN}/tokenbridge-e2e-monitor:${CIRCLE_BRANCH} - build: - context: .. - dockerfile: monitor/Dockerfile + image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local} env_file: ../e2e-commons/components-envs/monitor-erc20-native.env entrypoint: yarn check-and-start ports: @@ -157,10 +141,7 @@ services: networks: - ultimate monitor-amb: - image: ${DOCKER_LOGIN}/tokenbridge-e2e-monitor:${CIRCLE_BRANCH} - build: - context: .. - dockerfile: monitor/Dockerfile + image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-monitor:${MONITOR_TAG:-local} env_file: ../e2e-commons/components-envs/monitor-amb.env entrypoint: yarn check-and-start ports: @@ -168,7 +149,7 @@ services: networks: - ultimate e2e: - image: ${DOCKER_LOGIN}/tokenbridge-e2e-e2e:${CIRCLE_BRANCH} + image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-e2e:${E2E_TAG:-local} build: context: .. dockerfile: Dockerfile.e2e @@ -176,15 +157,12 @@ services: networks: - ultimate blocks: - image: ${DOCKER_LOGIN}/tokenbridge-e2e-e2e:${CIRCLE_BRANCH} - build: - context: .. - dockerfile: Dockerfile.e2e + image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-e2e:${E2E_TAG:-local} entrypoint: node e2e-commons/scripts/blocks.js networks: - ultimate molecule_runner: - image: ${DOCKER_LOGIN}/tokenbridge-e2e-molecule_runner:${CIRCLE_BRANCH} + image: ${DOCKER_IMAGE_BASE:-tokenbridge}/tokenbridge-e2e-molecule_runner:${MOLECULE_RUNNER_TAG:-local} build: context: .. dockerfile: deployment-e2e/Dockerfile diff --git a/e2e-commons/up.sh b/e2e-commons/up.sh index b54481aa..f0a367c0 100755 --- a/e2e-commons/up.sh +++ b/e2e-commons/up.sh @@ -4,7 +4,13 @@ set -e # exit when any command fails ./down.sh docker-compose build parity1 parity2 -test -n "$NODOCKERPULL" || ./pull.sh $@ + +if [ -z "$CI" ]; then + ./build.sh $@ +else + ./pull.sh $@ +fi + docker network create --driver bridge ultimate || true docker-compose up -d parity1 parity2 e2e @@ -107,26 +113,6 @@ while [ "$1" != "" ]; do docker-compose up -d monitor monitor-erc20 monitor-erc20-native monitor-amb fi - if [ "$1" == "native-to-erc" ]; then - ../deployment-e2e/molecule.sh ultimate-native-to-erc - fi - - if [ "$1" == "erc-to-native" ]; then - ../deployment-e2e/molecule.sh ultimate-erc-to-native - fi - - if [ "$1" == "erc-to-erc" ]; then - ../deployment-e2e/molecule.sh ultimate-erc-to-erc - fi - - if [ "$1" == "amb" ]; then - ../deployment-e2e/molecule.sh ultimate-amb - fi - - if [ "$1" == "ultimate-amb-stake-erc-to-erc" ]; then - ../deployment-e2e/molecule.sh ultimate-amb-stake-erc-to-erc - fi - if [ "$1" == "alm-e2e" ]; then docker-compose up -d redis rabbit diff --git a/monitor-e2e/package.json b/monitor-e2e/package.json index 66d8b436..4dbb50e6 100644 --- a/monitor-e2e/package.json +++ b/monitor-e2e/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "start": "mocha --timeout 30000", + "start": "mocha --timeout 120000", "lint": "eslint . --ignore-path ../.eslintignore" }, "author": "", diff --git a/monitor-e2e/periodically-check-all.sh b/monitor-e2e/periodically-check-all.sh index 251bad9a..dd5e0c98 100755 --- a/monitor-e2e/periodically-check-all.sh +++ b/monitor-e2e/periodically-check-all.sh @@ -1,7 +1,7 @@ while true; do - sleep 3 - COMPOSE_INTERACTIVE_NO_CLI=1 nohup docker-compose -f ../e2e-commons/docker-compose.yml exec monitor yarn check-all - COMPOSE_INTERACTIVE_NO_CLI=1 nohup docker-compose -f ../e2e-commons/docker-compose.yml exec monitor-erc20 yarn check-all - COMPOSE_INTERACTIVE_NO_CLI=1 nohup docker-compose -f ../e2e-commons/docker-compose.yml exec monitor-erc20-native yarn check-all - COMPOSE_INTERACTIVE_NO_CLI=1 nohup docker-compose -f ../e2e-commons/docker-compose.yml exec monitor-amb yarn check-all + sleep 5 + docker-compose -f ../e2e-commons/docker-compose.yml exec -d monitor yarn check-all + docker-compose -f ../e2e-commons/docker-compose.yml exec -d monitor-erc20 yarn check-all + docker-compose -f ../e2e-commons/docker-compose.yml exec -d monitor-erc20-native yarn check-all + docker-compose -f ../e2e-commons/docker-compose.yml exec -d monitor-amb yarn check-all done diff --git a/monitor-e2e/test/ercToNative.js b/monitor-e2e/test/ercToNative.js index aad7cdef..7810ed39 100644 --- a/monitor-e2e/test/ercToNative.js +++ b/monitor-e2e/test/ercToNative.js @@ -37,6 +37,9 @@ describe('ERC TO NATIVE with changing state of contracts', () => { await waitUntil(async () => { ;({ data } = await axios.get(`${baseUrl}`)) + if (!data.foreign) { + return false + } const { erc20Balance, investedErc20Balance } = data.foreign return data.balanceDiff === 0.01 && erc20Balance === '0.01' && investedErc20Balance === undefined }) @@ -58,6 +61,9 @@ describe('ERC TO NATIVE with changing state of contracts', () => { await waitUntil(async () => { ;({ data } = await axios.get(`${baseUrl}`)) const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign + if (!data.foreign) { + return false + } return ( data.balanceDiff === 0.02 && erc20Balance === '0.02' && @@ -72,6 +78,9 @@ describe('ERC TO NATIVE with changing state of contracts', () => { await waitUntil(async () => { ;({ data } = await axios.get(`${baseUrl}`)) const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign + if (!data.foreign) { + return false + } return ( data.balanceDiff === 0.02 && erc20Balance === '0.01' && @@ -86,6 +95,9 @@ describe('ERC TO NATIVE with changing state of contracts', () => { await waitUntil(async () => { ;({ data } = await axios.get(`${baseUrl}`)) const { erc20Balance, investedErc20Balance, accumulatedInterest } = data.foreign + if (!data.foreign) { + return false + } return ( data.balanceDiff === 0.02 && erc20Balance === '0.005' && diff --git a/monitor-e2e/utils.js b/monitor-e2e/utils.js index 6459ebfa..c7a9428a 100644 --- a/monitor-e2e/utils.js +++ b/monitor-e2e/utils.js @@ -8,7 +8,7 @@ const { } = require('../commons') const { validator } = require('../e2e-commons/constants') -const waitUntil = async (predicate, step = 100, timeout = 20000) => { +const waitUntil = async (predicate, step = 100, timeout = 60000) => { const stopTime = Date.now() + timeout while (Date.now() <= stopTime) { const result = await predicate() diff --git a/monitor-e2e/wait-for-monitor.sh b/monitor-e2e/wait-for-monitor.sh index bd0a775f..2b33b215 100755 --- a/monitor-e2e/wait-for-monitor.sh +++ b/monitor-e2e/wait-for-monitor.sh @@ -1,13 +1,15 @@ +#!/bin/bash + FILES=(getBalances.json validators.json eventsStats.json alerts.json) check_files_exist() { rc=0 for f in "${FILES[@]}"; do command="test -f responses/bridge/$f" - (docker-compose -f ../e2e-commons/docker-compose.yml exec monitor /bin/bash -c "$command") || rc=1 - (docker-compose -f ../e2e-commons/docker-compose.yml exec monitor-erc20 /bin/bash -c "$command") || rc=1 - (docker-compose -f ../e2e-commons/docker-compose.yml exec monitor-erc20-native /bin/bash -c "$command") || rc=1 - (docker-compose -f ../e2e-commons/docker-compose.yml exec monitor-amb /bin/bash -c "$command") || rc=1 + (docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor /bin/bash -c "$command") || rc=1 + (docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20 /bin/bash -c "$command") || rc=1 + (docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-erc20-native /bin/bash -c "$command") || rc=1 + (docker-compose -f ../e2e-commons/docker-compose.yml exec -T monitor-amb /bin/bash -c "$command") || rc=1 done return $rc } diff --git a/monitor/Dockerfile b/monitor/Dockerfile index 3d48c839..0aa618e8 100644 --- a/monitor/Dockerfile +++ b/monitor/Dockerfile @@ -1,4 +1,4 @@ -FROM node:8 as contracts +FROM node:10 as contracts WORKDIR /mono @@ -11,7 +11,7 @@ COPY ./contracts/truffle-config.js ./ COPY ./contracts/contracts ./contracts RUN npm run compile -FROM node:8 +FROM node:10 WORKDIR /mono COPY package.json . diff --git a/oracle/Dockerfile b/oracle/Dockerfile index 86a8866b..37cd5e26 100644 --- a/oracle/Dockerfile +++ b/oracle/Dockerfile @@ -1,4 +1,4 @@ -FROM node:8 as contracts +FROM node:10 as contracts WORKDIR /mono @@ -11,14 +11,11 @@ COPY ./contracts/truffle-config.js ./ COPY ./contracts/contracts ./contracts RUN npm run compile -FROM node:8 +FROM node:10 -RUN apt-get update -RUN apt-get install -y build-essential -RUN apt-get install -y libc6-dev -RUN apt-get install -y libc6-dev-i386 -RUN apt-get install -y wget -RUN apt-get clean +RUN apt-get update && \ + apt-get install -y build-essential libc6-dev libc6-dev-i386 wget && \ + apt-get clean WORKDIR /mono COPY package.json . diff --git a/oracle/config/affirmation-request-watcher.config.js b/oracle/config/affirmation-request-watcher.config.js index f91cc471..9ae5be43 100644 --- a/oracle/config/affirmation-request-watcher.config.js +++ b/oracle/config/affirmation-request-watcher.config.js @@ -24,7 +24,7 @@ module.exports = { ...baseConfig.bridgeConfig, ...baseConfig.foreignConfig, event: 'UserRequestForAffirmation', - queue: 'home', + queue: 'home-prioritized', name: `watcher-${id}`, id } diff --git a/oracle/config/base.config.js b/oracle/config/base.config.js index 1e2398cd..5808b5dd 100644 --- a/oracle/config/base.config.js +++ b/oracle/config/base.config.js @@ -73,6 +73,7 @@ const bridgeConfig = { } const homeConfig = { + chain: 'home', eventContractAddress: process.env.COMMON_HOME_BRIDGE_ADDRESS, eventAbi: homeAbi, bridgeContractAddress: process.env.COMMON_HOME_BRIDGE_ADDRESS, @@ -83,6 +84,7 @@ const homeConfig = { } const foreignConfig = { + chain: 'foreign', eventContractAddress: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS, eventAbi: foreignAbi, bridgeContractAddress: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS, diff --git a/oracle/config/collected-signatures-watcher.config.js b/oracle/config/collected-signatures-watcher.config.js index cdffa345..9340d13d 100644 --- a/oracle/config/collected-signatures-watcher.config.js +++ b/oracle/config/collected-signatures-watcher.config.js @@ -6,7 +6,7 @@ module.exports = { ...baseConfig.bridgeConfig, ...baseConfig.homeConfig, event: 'CollectedSignatures', - queue: 'foreign', + queue: 'foreign-prioritized', name: `watcher-${id}`, id } diff --git a/oracle/config/convert-to-chai-worker.config.js b/oracle/config/convert-to-chai-worker.config.js index f30189c7..8f30b098 100644 --- a/oracle/config/convert-to-chai-worker.config.js +++ b/oracle/config/convert-to-chai-worker.config.js @@ -14,7 +14,7 @@ module.exports = { ...baseConfig.bridgeConfig, ...baseConfig.foreignConfig, workerQueue: 'convert-to-chai', - senderQueue: 'foreign', + senderQueue: 'foreign-prioritized', name: `worker-${id}`, id } diff --git a/oracle/config/foreign-sender.config.js b/oracle/config/foreign-sender.config.js index c589a119..774f77ed 100644 --- a/oracle/config/foreign-sender.config.js +++ b/oracle/config/foreign-sender.config.js @@ -4,7 +4,8 @@ const { web3Foreign } = require('../src/services/web3') module.exports = { ...baseConfig.bridgeConfig, - queue: 'foreign', + queue: 'foreign-prioritized', + oldQueue: 'foreign', id: 'foreign', name: 'sender-foreign', web3: web3Foreign diff --git a/oracle/config/home-sender.config.js b/oracle/config/home-sender.config.js index cc5ab3a1..aed9fc9d 100644 --- a/oracle/config/home-sender.config.js +++ b/oracle/config/home-sender.config.js @@ -4,7 +4,8 @@ const { web3Home } = require('../src/services/web3') module.exports = { ...baseConfig.bridgeConfig, - queue: 'home', + queue: 'home-prioritized', + oldQueue: 'home', id: 'home', name: 'sender-home', web3: web3Home diff --git a/oracle/config/signature-request-watcher.config.js b/oracle/config/signature-request-watcher.config.js index a487c432..60d9a805 100644 --- a/oracle/config/signature-request-watcher.config.js +++ b/oracle/config/signature-request-watcher.config.js @@ -6,7 +6,7 @@ module.exports = { ...baseConfig.bridgeConfig, ...baseConfig.homeConfig, event: 'UserRequestForSignature', - queue: 'home', + queue: 'home-prioritized', name: `watcher-${id}`, id } diff --git a/oracle/config/transfer-watcher.config.js b/oracle/config/transfer-watcher.config.js index 76c30995..c7c82282 100644 --- a/oracle/config/transfer-watcher.config.js +++ b/oracle/config/transfer-watcher.config.js @@ -41,7 +41,7 @@ module.exports = { eventContractAddress: initialChecks.bridgeableTokenAddress, eventAbi: ERC20_ABI, eventFilter: { to: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS }, - queue: 'home', + queue: 'home-prioritized', ...workerQueueConfig, name: `watcher-${id}`, id diff --git a/oracle/src/confirmRelay.js b/oracle/src/confirmRelay.js index 57f2c18a..d7b45043 100644 --- a/oracle/src/confirmRelay.js +++ b/oracle/src/confirmRelay.js @@ -138,8 +138,8 @@ async function main({ sendJob, txHash }) { } async function sendJobTx(jobs) { - const gasPrice = await GasPrice.start(config.queue, true) - const chainId = await getChainId(config.queue) + const gasPrice = await GasPrice.start(config.chain, true) + const chainId = await getChainId(config.chain) let nonce = await getNonce(web3Instance, ORACLE_VALIDATOR_ADDRESS) await syncForEach(jobs, async job => { @@ -153,7 +153,7 @@ async function sendJobTx(jobs) { try { logger.info(`Sending transaction with nonce ${nonce}`) const txHash = await sendTx({ - chain: config.queue, + chain: config.chain, data: job.data, nonce, gasPrice: gasPrice.toString(10), diff --git a/oracle/src/sender.js b/oracle/src/sender.js index 10515cb9..c6fbde30 100644 --- a/oracle/src/sender.js +++ b/oracle/src/sender.js @@ -1,5 +1,6 @@ require('../env') const path = require('path') +const { toBN } = require('web3-utils') const { connectSenderToQueue } = require('./services/amqpClient') const { redis } = require('./services/redisClient') const GasPrice = require('./services/gasPrice') @@ -45,6 +46,7 @@ async function initialize() { chainId = await getChainId(config.id) connectSenderToQueue({ queueName: config.queue, + oldQueueName: config.oldQueue, cb: options => { if (config.maxProcessingTime) { return watchdog(() => main(options), config.maxProcessingTime, () => { @@ -88,7 +90,7 @@ function updateNonce(nonce) { return redis.set(nonceKey, nonce) } -async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry }) { +async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry, scheduleTransactionResend }) { try { if (redis.status !== 'ready') { nackMsg(msg) @@ -103,8 +105,15 @@ async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry }) { let insufficientFunds = false let minimumBalance = null const failedTx = [] + const sentTx = [] - logger.debug(`Sending ${txArray.length} transactions`) + const isResend = txArray.length > 0 && !!txArray[0].txHash + + if (isResend) { + logger.debug(`Checking status of ${txArray.length} transactions`) + } else { + logger.debug(`Sending ${txArray.length} transactions`) + } await syncForEach(txArray, async job => { let gasLimit if (typeof job.extraGas === 'number') { @@ -114,11 +123,37 @@ async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry }) { } try { - logger.info(`Sending transaction with nonce ${nonce}`) + let txNonce + if (isResend) { + const tx = await web3Instance.eth.getTransaction(job.txHash) + + if (tx === null) { + logger.info(`Transaction ${job.txHash} was not found, dropping it`) + return + } + if (tx.blockNumber !== null) { + logger.info(`Transaction ${job.txHash} was successfully mined`) + return + } + + logger.info( + `Previously sent transaction is stuck, updating gasPrice: ${tx.gasPrice} -> ${gasPrice.toString(10)}` + ) + if (toBN(tx.gasPrice).gte(toBN(gasPrice))) { + logger.info("Gas price returned from the oracle didn't increase, will reinspect this transaction later") + sentTx.push(job) + return + } + + txNonce = tx.nonce + } else { + txNonce = nonce++ + } + logger.info(`Sending transaction with nonce ${txNonce}`) const txHash = await sendTx({ chain: config.id, data: job.data, - nonce, + nonce: txNonce, gasPrice: gasPrice.toString(10), amount: '0', gasLimit, @@ -127,8 +162,11 @@ async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry }) { chainId, web3: web3Instance }) + sentTx.push({ + ...job, + txHash + }) - nonce++ logger.info( { eventTransactionHash: job.transactionReference, generatedTransactionHash: txHash }, `Tx generated ${txHash} for event Tx ${job.transactionReference}` @@ -163,6 +201,10 @@ async function main({ msg, ackMsg, nackMsg, channel, scheduleForRetry }) { logger.info(`Sending ${failedTx.length} Failed Tx to Queue`) await scheduleForRetry(failedTx, msg.properties.headers['x-retries']) } + if (sentTx.length) { + logger.info(`Sending ${sentTx.length} Tx Delayed Resend Requests to Queue`) + await scheduleTransactionResend(sentTx) + } ackMsg(msg) logger.debug(`Finished processing msg`) diff --git a/oracle/src/services/RpcUrlsManager.js b/oracle/src/services/RpcUrlsManager.js index 7ee9e652..dba8d7cc 100644 --- a/oracle/src/services/RpcUrlsManager.js +++ b/oracle/src/services/RpcUrlsManager.js @@ -11,8 +11,8 @@ function RpcUrlsManager(homeUrls, foreignUrls) { throw new Error(`Invalid foreignUrls: '${foreignUrls}'`) } - this.homeUrls = homeUrls.split(',') - this.foreignUrls = foreignUrls.split(',') + this.homeUrls = homeUrls.split(' ') + this.foreignUrls = foreignUrls.split(' ') } RpcUrlsManager.prototype.tryEach = async function(chain, f, redundant = false) { diff --git a/oracle/src/services/amqpClient.js b/oracle/src/services/amqpClient.js index 3e0f6823..86bbb19a 100644 --- a/oracle/src/services/amqpClient.js +++ b/oracle/src/services/amqpClient.js @@ -4,6 +4,12 @@ const dns = require('dns') const connection = require('amqp-connection-manager').connect(process.env.ORACLE_QUEUE_URL) const logger = require('./logger') const { getRetrySequence } = require('../utils/utils') +const { + TRANSACTION_RESEND_TIMEOUT, + SENDER_QUEUE_MAX_PRIORITY, + SENDER_QUEUE_SEND_PRIORITY, + SENDER_QUEUE_CHECK_STATUS_PRIORITY +} = require('../utils/constants') connection.on('connect', () => { logger.info('Connected to amqp Broker') @@ -22,16 +28,18 @@ async function isAttached() { } function connectWatcherToQueue({ queueName, workerQueue, cb }) { - const queueList = workerQueue ? [queueName, workerQueue] : [queueName] - const channelWrapper = connection.createChannel({ json: true, - setup(channel) { - return Promise.all(queueList.map(queue => channel.assertQueue(queue, { durable: true }))) + async setup(channel) { + await channel.assertQueue(queueName, { durable: true, maxPriority: SENDER_QUEUE_MAX_PRIORITY }) + if (workerQueue) { + await channel.assertQueue(workerQueue, { durable: true }) + } } }) - const sendToQueue = data => channelWrapper.sendToQueue(queueName, data, { persistent: true }) + const sendToQueue = data => + channelWrapper.sendToQueue(queueName, data, { persistent: true, priority: SENDER_QUEUE_SEND_PRIORITY }) let sendToWorker if (workerQueue) { sendToWorker = data => channelWrapper.sendToQueue(workerQueue, data, { persistent: true }) @@ -40,38 +48,60 @@ function connectWatcherToQueue({ queueName, workerQueue, cb }) { cb({ sendToQueue, sendToWorker, channel: channelWrapper }) } -function connectSenderToQueue({ queueName, cb }) { +function connectSenderToQueue({ queueName, oldQueueName, cb }) { const deadLetterExchange = `${queueName}-retry` + async function resendMessagesToNewQueue(channel) { + logger.info(`Trying to check messages in the old non-priority queue ${queueName}`) + while (true) { + const msg = await channel.get(oldQueueName) + if (msg === false) { + logger.info(`No messages in the old queue ${oldQueueName} left`) + break + } + logger.debug(`Message in the old queue ${oldQueueName} was found, redirecting it to the new queue ${queueName}`) + await channel.sendToQueue(queueName, msg.content, { persistent: true, priority: SENDER_QUEUE_SEND_PRIORITY }) + await channel.ack(msg) + } + } + const channelWrapper = connection.createChannel({ json: true }) - channelWrapper.addSetup(channel => { - return Promise.all([ - channel.assertExchange(deadLetterExchange, 'fanout', { durable: true }), - channel.assertQueue(queueName, { durable: true }), - channel.bindQueue(queueName, deadLetterExchange), - channel.prefetch(1), - channel.consume(queueName, msg => - cb({ - msg, - channel: channelWrapper, - ackMsg: job => channelWrapper.ack(job), - nackMsg: job => channelWrapper.nack(job, false, true), - scheduleForRetry: async (data, msgRetries = 0) => { - await generateRetry({ - data, - msgRetries, - channelWrapper, - channel, - queueName, - deadLetterExchange - }) - } - }) - ) - ]) + channelWrapper.addSetup(async channel => { + await channel.assertExchange(deadLetterExchange, 'fanout', { durable: true }) + await channel.assertQueue(queueName, { durable: true, maxPriority: SENDER_QUEUE_MAX_PRIORITY }) + await channel.assertQueue(oldQueueName, { durable: true }).then(() => resendMessagesToNewQueue(channel)) + await channel.bindQueue(queueName, deadLetterExchange) + await channel.prefetch(1) + await channel.consume(queueName, msg => + cb({ + msg, + channel: channelWrapper, + ackMsg: job => channelWrapper.ack(job), + nackMsg: job => channelWrapper.nack(job, false, true), + scheduleForRetry: async (data, msgRetries = 0) => { + await generateRetry({ + data, + msgRetries, + channelWrapper, + channel, + queueName, + deadLetterExchange + }) + }, + scheduleTransactionResend: async data => { + await generateTransactionResend({ + data, + channelWrapper, + channel, + queueName, + deadLetterExchange + }) + } + }) + ) }) } @@ -82,52 +112,73 @@ function connectWorkerToQueue({ queueName, senderQueue, cb }) { json: true }) - channelWrapper.addSetup(channel => { - return Promise.all([ - channel.assertExchange(deadLetterExchange, 'fanout', { durable: true }), - channel.assertQueue(queueName, { durable: true }), - channel.assertQueue(senderQueue, { durable: true }), - channel.bindQueue(queueName, deadLetterExchange), - channel.prefetch(1), - channel.consume(queueName, msg => - cb({ - msg, - channel: channelWrapper, - ackMsg: job => channelWrapper.ack(job), - nackMsg: job => channelWrapper.nack(job, false, true), - sendToSenderQueue: data => channelWrapper.sendToQueue(senderQueue, data, { persistent: true }), - scheduleForRetry: async (data, msgRetries = 0) => { - await generateRetry({ - data, - msgRetries, - channelWrapper, - channel, - queueName, - deadLetterExchange - }) - } - }) - ) - ]) + channelWrapper.addSetup(async channel => { + await channel.assertExchange(deadLetterExchange, 'fanout', { durable: true }) + await channel.assertQueue(queueName, { durable: true }) + await channel.assertQueue(senderQueue, { durable: true, maxPriority: SENDER_QUEUE_MAX_PRIORITY }) + await channel.bindQueue(queueName, deadLetterExchange) + await channel.prefetch(1) + await channel.consume(queueName, msg => + cb({ + msg, + channel: channelWrapper, + ackMsg: job => channelWrapper.ack(job), + nackMsg: job => channelWrapper.nack(job, false, true), + sendToSenderQueue: data => + channelWrapper.sendToQueue(senderQueue, data, { persistent: true, priority: SENDER_QUEUE_SEND_PRIORITY }), + scheduleForRetry: async (data, msgRetries = 0) => { + await generateRetry({ + data, + msgRetries, + channelWrapper, + channel, + queueName, + deadLetterExchange + }) + } + }) + ) }) } async function generateRetry({ data, msgRetries, channelWrapper, channel, queueName, deadLetterExchange }) { const retries = msgRetries + 1 const delay = getRetrySequence(retries) * 1000 + + // New retry queue is created, and one message is send to it. + // Nobody consumes messages from this queue, so eventually the message will be dropped. + // `messageTtl` defines a timeout after which the message will be dropped out of the queue. + // When message is dropped, it will be resend into the specified `deadLetterExchange` with the updated `x-retries` header. const retryQueue = `${queueName}-retry-${delay}` await channel.assertQueue(retryQueue, { durable: true, deadLetterExchange, messageTtl: delay, - expires: delay * 10 + expires: delay * 10, + maxPriority: SENDER_QUEUE_MAX_PRIORITY }) await channelWrapper.sendToQueue(retryQueue, data, { persistent: true, + priority: SENDER_QUEUE_SEND_PRIORITY, headers: { 'x-retries': retries } }) } +async function generateTransactionResend({ data, channelWrapper, channel, queueName, deadLetterExchange }) { + const retryQueue = `${queueName}-check-tx-status` + await channel.assertQueue(retryQueue, { + durable: true, + deadLetterExchange, + messageTtl: TRANSACTION_RESEND_TIMEOUT, + expires: TRANSACTION_RESEND_TIMEOUT * 10, + maxPriority: SENDER_QUEUE_MAX_PRIORITY + }) + await channelWrapper.sendToQueue(retryQueue, data, { + priority: SENDER_QUEUE_CHECK_STATUS_PRIORITY, + persistent: true + }) +} + module.exports = { isAttached, connectWatcherToQueue, diff --git a/oracle/src/utils/constants.js b/oracle/src/utils/constants.js index 7d6fc24c..e1fcb20b 100644 --- a/oracle/src/utils/constants.js +++ b/oracle/src/utils/constants.js @@ -22,5 +22,9 @@ module.exports = { GAS_PRICE_BOUNDARIES: { MIN: 1, MAX: 250 - } + }, + TRANSACTION_RESEND_TIMEOUT: 20 * 60 * 1000, + SENDER_QUEUE_MAX_PRIORITY: 10, + SENDER_QUEUE_SEND_PRIORITY: 5, + SENDER_QUEUE_CHECK_STATUS_PRIORITY: 1 } diff --git a/oracle/src/utils/utils.js b/oracle/src/utils/utils.js index a191e2cb..8de376ff 100644 --- a/oracle/src/utils/utils.js +++ b/oracle/src/utils/utils.js @@ -33,7 +33,7 @@ async function waitForFunds(web3, address, minimumBalance, cb, logger) { async retry => { logger.debug('Getting balance of validator account') const newBalance = web3.utils.toBN(await web3.eth.getBalance(address)) - if (newBalance.gte(minimumBalance)) { + if (newBalance.gte(web3.utils.toBN(minimumBalance.toString(10)))) { logger.debug({ balance: newBalance, minimumBalance }, 'Validator has minimum necessary balance') cb(newBalance) } else { diff --git a/oracle/test/gasPrice.test.js b/oracle/test/gasPrice.test.js index fc462db7..d1fac2c8 100644 --- a/oracle/test/gasPrice.test.js +++ b/oracle/test/gasPrice.test.js @@ -73,7 +73,7 @@ describe('gasPrice', () => { await gasPrice.start('home') // when - await gasPrice.fetchGasPrice('standard', 1, null, null) + await gasPrice.fetchGasPrice('standard', 1, null, () => null) // then expect(gasPrice.getPrice()).to.equal('101000000000') @@ -113,7 +113,7 @@ describe('gasPrice', () => { } // when - await gasPrice.fetchGasPrice('standard', 1, bridgeContractMock, null) + await gasPrice.fetchGasPrice('standard', 1, bridgeContractMock, () => {}) // then expect(gasPrice.getPrice().toString()).to.equal('102000000000') @@ -156,7 +156,7 @@ describe('gasPrice', () => { await gasPrice.start('home') // when - await gasPrice.fetchGasPrice('standard', 1, null, null) + await gasPrice.fetchGasPrice('standard', 1, null, () => {}) // then expect(fakeLogger.error.calledTwice).to.equal(true) // two errors diff --git a/package.json b/package.json index 85981a05..af29d73d 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "test": "yarn wsrun --exclude oracle-e2e --exclude ui-e2e --exclude monitor-e2e --exclude alm-e2e test", "oracle-e2e": "./oracle-e2e/run-tests.sh", "ui-e2e": "./ui-e2e/run-tests.sh", + "ui-e2e:ci": "xvfb-run yarn ui-e2e", "monitor-e2e": "./monitor-e2e/run-tests.sh", "alm-e2e": "./alm-e2e/run-tests.sh", "clean": "rm -rf ./node_modules ./**/node_modules ./**/**/node_modules ./**/build ./**/**/dist", diff --git a/ui-e2e/MetaMask.crx b/ui-e2e/MetaMask.crx index 6f4bd0f8..76351316 100644 Binary files a/ui-e2e/MetaMask.crx and b/ui-e2e/MetaMask.crx differ diff --git a/ui-e2e/MetaMask.js b/ui-e2e/MetaMask.js index f640db86..0e8e9ebf 100644 --- a/ui-e2e/MetaMask.js +++ b/ui-e2e/MetaMask.js @@ -3,7 +3,7 @@ const { By } = require('selenium-webdriver/lib/by') const { Page } = require('./Page.js') const { homeRPC, foreignRPC } = require('../e2e-commons/constants.json') -const IDMetaMask = 'dapggmdndodedfoaljbglbkaicfpmkkm' +const IDMetaMask = 'hccmbhdehlhjhkenmcjnbcahkmljpife' const URL = 'chrome-extension://' + IDMetaMask + '//popup.html' const buttonSubmit = By.className('confirm btn-green') const buttonAccept = By.xpath('//*[@id="app-content"]/div/div[4]/div/button') diff --git a/ui-e2e/Utils.js b/ui-e2e/Utils.js index 5b20604a..390469ee 100644 --- a/ui-e2e/Utils.js +++ b/ui-e2e/Utils.js @@ -46,8 +46,11 @@ class Utils { static async startBrowserWithMetamask() { const source = './MetaMask.crx' const options = new chrome.Options() - await options.addExtensions(source) + await options.addArguments('--no-sandbox') + await options.addArguments('--disable-gpu') + await options.addArguments('--disable-dev-shm-usage') await options.addArguments('disable-popup-blocking') + await options.addExtensions(source) const driver = await new webdriver.Builder().withCapabilities(options.toCapabilities()).build() await driver.sleep(5000) return driver diff --git a/ui-e2e/package.json b/ui-e2e/package.json index aca56fc0..d065273b 100644 --- a/ui-e2e/package.json +++ b/ui-e2e/package.json @@ -4,7 +4,6 @@ "license": "MIT", "private": true, "devDependencies": { - "chromedriver": "^77.0.0", "mocha": "^5.2.0", "selenium-webdriver": "3.6.0" }, diff --git a/ui-e2e/run-tests.sh b/ui-e2e/run-tests.sh index 53804cbc..9e25646f 100755 --- a/ui-e2e/run-tests.sh +++ b/ui-e2e/run-tests.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash + cd $(dirname $0) ../e2e-commons/up.sh deploy oracle ui blocks diff --git a/ui-e2e/test.js b/ui-e2e/test.js index 26ed201c..60885913 100644 --- a/ui-e2e/test.js +++ b/ui-e2e/test.js @@ -83,7 +83,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { const shouldBe = homeBalanceBefore - maxAmountPerTransactionLimit console.log('newHomeBalance = ' + newHomeBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 10 homeBalanceBefore = newHomeBalance return await assert.strictEqual(result, true, 'Test FAILED.Home POA balance is not correct after transaction') }) @@ -95,7 +95,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { console.log('newForeignBalance = ' + newForeignBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 10 return await assert.strictEqual(result, true, 'Test FAILED. Foreign POA balance is not correct after transaction') }) @@ -115,7 +115,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { const shouldBe = foreignBalanceBefore - maxAmountPerTransactionLimit console.log('newForeignBalance = ' + newForeignBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 10 return await assert.strictEqual(result, true, 'Test FAILED.Foreign POA balance is not correct after transaction') }) @@ -124,7 +124,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { const shouldBe = homeBalanceBefore + maxAmountPerTransactionLimit console.log('newHomeBalance = ' + newHomeBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 10 return await assert.strictEqual(result, true, 'Test FAILED.Home POA balance is not correct after transaction') }) }) @@ -173,7 +173,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { const shouldBe = foreignBalanceBefore - maxAmountPerTransactionLimit console.log('newForeignBalance = ' + newForeignBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 10 return await assert.strictEqual(result, true, 'Test FAILED.Foreign POA balance is not correct after transaction') }) @@ -182,7 +182,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { const shouldBe = homeBalanceBefore + maxAmountPerTransactionLimit console.log('newHomeBalance = ' + newHomeBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 10 return await assert.strictEqual(result, true, 'Test FAILED.Home POA balance is not correct after transaction') }) test.it('User is able to send tokens from Home account to Foreign account ', async () => { @@ -202,7 +202,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { const shouldBe = homeBalanceBefore - maxAmountPerTransactionLimit console.log('newHomeBalance = ' + newHomeBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 10 homeBalanceBefore = newHomeBalance return await assert.strictEqual(result, true, 'Test FAILED.Home POA balance is not correct after transaction') }) @@ -214,7 +214,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { console.log('newForeignBalance = ' + newForeignBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 10 return await assert.strictEqual(result, true, 'Test FAILED. Foreign POA balance is not correct after transaction') }) }) @@ -263,7 +263,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { const shouldBe = foreignBalanceBefore - maxAmountPerTransactionLimit console.log('newForeignBalance = ' + newForeignBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 10 return await assert.strictEqual(result, true, 'Test FAILED.Foreign POA balance is not correct after transaction') }) @@ -272,7 +272,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { const shouldBe = homeBalanceBefore + maxAmountPerTransactionLimit console.log('newHomeBalance = ' + newHomeBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 10 return await assert.strictEqual(result, true, 'Test FAILED.Home POA balance is not correct after transaction') }) test.it('User is able to send tokens from Home account to Foreign account', async () => { @@ -292,7 +292,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { const shouldBe = homeBalanceBefore - maxAmountPerTransactionLimit console.log('newHomeBalance = ' + newHomeBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 10 homeBalanceBefore = newHomeBalance return await assert.strictEqual(result, true, 'Test FAILED.Home POA balance is not correct after transaction') }) @@ -304,7 +304,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { console.log('newForeignBalance = ' + newForeignBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 10 return await assert.strictEqual(result, true, 'Test FAILED. Foreign POA balance is not correct after transaction') }) }) @@ -353,7 +353,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { const shouldBe = foreignBalanceBefore - maxAmountPerTransactionLimit console.log('newForeignBalance = ' + newForeignBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 10 return await assert.strictEqual(result, true, 'Test FAILED.Foreign POA balance is not correct after transaction') }) @@ -362,7 +362,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { const shouldBe = homeBalanceBefore + maxAmountPerTransactionLimit console.log('newHomeBalance = ' + newHomeBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 10 return await assert.strictEqual(result, true, 'Test FAILED.Home POA balance is not correct after transaction') }) test.it('User is able to send tokens from Home account to Foreign account', async () => { @@ -382,7 +382,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { const shouldBe = homeBalanceBefore - maxAmountPerTransactionLimit console.log('newHomeBalance = ' + newHomeBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newHomeBalance) < maxAmountPerTransactionLimit / 10 homeBalanceBefore = newHomeBalance return await assert.strictEqual(result, true, 'Test FAILED.Home POA balance is not correct after transaction') }) @@ -394,7 +394,7 @@ test.describe('e2e-test for bridge.poa, version 1.5.0', async function() { console.log('newForeignBalance = ' + newForeignBalance) console.log('shouldBe = ' + shouldBe) - const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 100 + const result = Math.abs(shouldBe - newForeignBalance) < maxAmountPerTransactionLimit / 10 return await assert.strictEqual(result, true, 'Test FAILED. Foreign POA balance is not correct after transaction') }) }) diff --git a/ui/Dockerfile b/ui/Dockerfile index 90f6aab0..333d69d4 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -1,4 +1,4 @@ -FROM node:8 as contracts +FROM node:10 as contracts WORKDIR /mono @@ -11,7 +11,7 @@ COPY ./contracts/truffle-config.js ./ COPY ./contracts/contracts ./contracts RUN npm run compile -FROM node:8 +FROM node:10 WORKDIR /mono COPY package.json . diff --git a/ui/package.json b/ui/package.json index b2d1f6fc..edfb4d45 100644 --- a/ui/package.json +++ b/ui/package.json @@ -5,7 +5,6 @@ "dependencies": { "@babel/plugin-proposal-decorators": "^7.4.0", "bignumber.js": "^6.0.0", - "coveralls": "^3.0.0", "customize-cra": "^0.2.12", "date-fns": "^2.13.0", "dotenv": "^7.0.0", @@ -37,7 +36,6 @@ "test": "react-app-rewired test --env=jsdom --no-watch", "test:watch": "react-app-rewired test --env=jsdom", "coverage": "react-app-rewired test --env=jsdom --coverage", - "coveralls": "cat ./coverage/lcov.info | node node_modules/.bin/coveralls", "eject": "react-app-rewired eject", "postinstall": "(cp lib/web3-eth/index.js ../node_modules/web3-eth/src; cp lib/web3-eth/index.js ./node_modules/web3-eth/src) || :" }, diff --git a/yarn.lock b/yarn.lock index 2263a441..d40781a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5847,17 +5847,6 @@ chrome-trace-event@^1.0.0: dependencies: tslib "^1.9.0" -chromedriver@^77.0.0: - version "77.0.0" - resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-77.0.0.tgz#bd916cc87a0ccb7a6e4fb4b43cb2368bc54db6a0" - integrity sha512-mZa1IVx4HD8rDaItWbnS470mmypgiWsDiu98r0NkiT4uLm3qrANl4vOU6no6vtWtLQiW5kt1POcIbjeNpsLbXA== - dependencies: - del "^4.1.1" - extract-zip "^1.6.7" - mkdirp "^0.5.1" - request "^2.88.0" - tcp-port-used "^1.0.1" - ci-info@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" @@ -6242,7 +6231,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@1.6.2, concat-stream@^1.5.0, concat-stream@^1.5.1, concat-stream@^1.6.0, concat-stream@^1.6.2: +concat-stream@^1.5.0, concat-stream@^1.5.1, concat-stream@^1.6.0, concat-stream@^1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -6557,18 +6546,6 @@ cosmiconfig@^5.0.0, cosmiconfig@^5.0.7, cosmiconfig@^5.1.0, cosmiconfig@^5.2.0: js-yaml "^3.13.1" parse-json "^4.0.0" -coveralls@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.3.tgz#83b1c64aea1c6afa69beaf50b55ac1bc4d13e2b8" - integrity sha512-viNfeGlda2zJr8Gj1zqXpDMRjw9uM54p7wzZdvLRyOgnAfCe974Dq4veZkjJdxQXbmdppu6flEajFYseHYaUhg== - dependencies: - growl "~> 1.10.0" - js-yaml "^3.11.0" - lcov-parse "^0.0.10" - log-driver "^1.2.7" - minimist "^1.2.0" - request "^2.86.0" - coveralls@^3.0.6: version "3.0.11" resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.11.tgz#e141da0922b632fcc66620f334460c3f0026a4ce" @@ -7061,13 +7038,6 @@ debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" -debug@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87" - integrity sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg== - dependencies: - ms "^2.1.1" - debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -7199,7 +7169,7 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deep-is@^0.1.3, deep-is@~0.1.3: +deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= @@ -7309,19 +7279,6 @@ del@^3.0.0: pify "^3.0.0" rimraf "^2.2.8" -del@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" - integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== - dependencies: - "@types/glob" "^7.1.1" - globby "^6.1.0" - is-path-cwd "^2.0.0" - is-path-in-cwd "^2.0.0" - p-map "^2.0.0" - pify "^4.0.1" - rimraf "^2.6.3" - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -9108,16 +9065,6 @@ extract-comments@^1.1.0: esprima-extract-comments "^1.1.0" parse-code-context "^1.0.0" -extract-zip@^1.6.7: - version "1.6.7" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9" - integrity sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k= - dependencies: - concat-stream "1.6.2" - debug "2.6.9" - mkdirp "0.5.1" - yauzl "2.4.1" - extract-zip@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" @@ -9234,13 +9181,6 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" -fd-slicer@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" - integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU= - dependencies: - pend "~1.2.0" - fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" @@ -10331,7 +10271,7 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.6: resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= -growl@1.10.5, "growl@~> 1.10.0": +growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== @@ -11571,11 +11511,6 @@ is-path-cwd@^1.0.0: resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= -is-path-cwd@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - is-path-in-cwd@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" @@ -11583,13 +11518,6 @@ is-path-in-cwd@^1.0.0: dependencies: is-path-inside "^1.0.0" -is-path-in-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" - integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== - dependencies: - is-path-inside "^2.1.0" - is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" @@ -11597,13 +11525,6 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-path-inside@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" - integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== - dependencies: - path-is-inside "^1.0.2" - is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -11734,11 +11655,6 @@ is-unc-path@^1.0.0: dependencies: unc-path-regex "^0.1.2" -is-url@^1.2.2: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" - integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== - is-utf8@^0.2.0, is-utf8@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" @@ -11764,15 +11680,6 @@ is-wsl@^1.1.0: resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= -is2@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is2/-/is2-2.0.1.tgz#8ac355644840921ce435d94f05d3a94634d3481a" - integrity sha512-+WaJvnaA7aJySz2q/8sLjMb2Mw14KTplHmSwcSpZ/fWJPkUmqw3YTzSWbPJ7OAwRvdYTWF2Wg+yYJ1AdP5Z8CA== - dependencies: - deep-is "^0.1.3" - ip-regex "^2.1.0" - is-url "^1.2.2" - isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -12438,7 +12345,7 @@ js-tokens@^3.0.0, js-tokens@^3.0.2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.9.0: +js-yaml@3.x, js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.9.0: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -12826,11 +12733,6 @@ lcid@^2.0.0: dependencies: invert-kv "^2.0.0" -lcov-parse@^0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" - integrity sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM= - lcov-parse@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" @@ -15080,7 +14982,7 @@ p-map@^1.1.1: resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA== -p-map@^2.0.0, p-map@^2.1.0: +p-map@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== @@ -17540,7 +17442,7 @@ request@^2.67.0, request@^2.85.0, request@^2.87.0, request@^2.88.0: tunnel-agent "^0.6.0" uuid "^3.3.2" -request@^2.79.0, request@^2.86.0: +request@^2.79.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== @@ -19382,14 +19284,6 @@ tar@^4.0.2, tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: safe-buffer "^5.1.2" yallist "^3.0.3" -tcp-port-used@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tcp-port-used/-/tcp-port-used-1.0.1.tgz#46061078e2d38c73979a2c2c12b5a674e6689d70" - integrity sha512-rwi5xJeU6utXoEIiMvVBMc9eJ2/ofzB+7nLOdnZuFTmNCLqRiQh2sMG9MqCxHU/69VC/Fwp5dV9306Qd54ll1Q== - dependencies: - debug "4.1.0" - is2 "2.0.1" - temp-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" @@ -22433,13 +22327,6 @@ yargs@^7.0.0, yargs@^7.1.0: y18n "^3.2.1" yargs-parser "^5.0.0" -yauzl@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" - integrity sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU= - dependencies: - fd-slicer "~1.0.1" - yauzl@^2.10.0, yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"